You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In code which needs to test fork and other process related functions, it should be possible to disable the interrupt handler, which interferes with code which has it's own signal handlers.
#!/usr/bin/env rspec
RSpec.describe "fork" do
it "handles interrupt correctly" do
pid = fork do
trap(:INT, :DEFAULT)
sleep
end
Process.kill(:INT, pid)
sleep(1)
result = Process.wait(pid, Process::WNOHANG)
expect(result).to_not be_nil
end
end
edit: deleted comment was duplicate code, removed for clarity
Thats less than ideal... but you might be waiting forever with no way to quit if you disabled our handler, I'm not adverse to adding a way to suppress it however...
Is it possible to remove them? I vaguely remember issues with puma in a similar vein, I'm wondering if we can provide a method instead, wrap a test inside a "no trap" handler which has a backup timeout kill before restoring the old one?
As signals are part of user code state, even if it's not traditionally something that needs to be tested, it does affect the behaviour of user-facing interfaces.
So, my suggestion would be to find a different solution. If the user presses Ctrl-C, the main thread will raise an Interrupt exception by default. I'd suggest you catch this instead.
So:
def run_tests
end
def run_all
begin
run_tests
rescue Interrupt
# exit and cancel current test
end
end
Also, another point, pressing Ctrl-C, I expect a backtrace, but right now it gets swallowed up and often I never see it if the test has actually failed due to some blocking operation - presssing Ctrl-C to cancel the tests doesn't print any output.
The expected behaviour is that the first Ctrl-C prints a message but carries on waiting for the current test to finish. The second Ctrl-C causes a hard exit. We do this because it allows cleanup to run for tests that aren't blocked, so in the case of the majority of tests they get a clean exit, but we also allow overriding that as a, no now, type deal.
Not intentional, just a side effect of implementation, a second Ctrl-C causes us to exit, there is no backtrace as this is an intended Ruby exit, not a crash. I don't think we could display a stacktrace if we even wanted to...
I think you should make this behaviour optional and I'd probably immediately disable it in my template Rspec configuration, because I find it so annoying when debugging that exceptions are swallowed and backtraces are not printed.
Activity
pirj commentedon Jan 22, 2020
@ioquatix can you please submit a minimal reproduction case that fails with
trap_interrupt
, but is passing without it?JonRowe commentedon Jan 22, 2020
Hm, they carry over to children? I mean we trap our
INT
forCtrl C
, without it theres no way to hard interrupt us.ioquatix commentedon Jan 22, 2020
Yes it carries to children.
ioquatix commentedon Jan 22, 2020
Here is a working example:
JonRowe commentedon Jan 22, 2020
edit: deleted comment was duplicate code, removed for clarity
Thats less than ideal... but you might be waiting forever with no way to quit if you disabled our handler, I'm not adverse to adding a way to suppress it however...
JonRowe commentedon Jan 22, 2020
Is it possible to remove them? I vaguely remember issues with puma in a similar vein, I'm wondering if we can provide a method instead, wrap a test inside a "no trap" handler which has a backup timeout kill before restoring the old one?
ioquatix commentedon Jan 22, 2020
If I was building RSpec, I'd want it to be minimally invasive on program state.
Even minitest gets this quite wrong IMHO: minitest/minitest#429
As signals are part of user code state, even if it's not traditionally something that needs to be tested, it does affect the behaviour of user-facing interfaces.
So, my suggestion would be to find a different solution. If the user presses Ctrl-C, the main thread will raise an
Interrupt
exception by default. I'd suggest you catch this instead.So:
ioquatix commentedon Jan 22, 2020
Also, another point, pressing Ctrl-C, I expect a backtrace, but right now it gets swallowed up and often I never see it if the test has actually failed due to some blocking operation - presssing Ctrl-C to cancel the tests doesn't print any output.
JonRowe commentedon Jan 22, 2020
The expected behaviour is that the first
Ctrl-C
prints a message but carries on waiting for the current test to finish. The secondCtrl-C
causes a hard exit. We do this because it allows cleanup to run for tests that aren't blocked, so in the case of the majority of tests they get a clean exit, but we also allow overriding that as a, no now, type deal.ioquatix commentedon Jan 23, 2020
If the test will never finish, pressing Ctrl-C a second time exits with no backtrace. Is this intentional?
JonRowe commentedon Jan 23, 2020
Not intentional, just a side effect of implementation, a second
Ctrl-C
causes us to exit, there is no backtrace as this is an intended Ruby exit, not a crash. I don't think we could display a stacktrace if we even wanted to...ioquatix commentedon Jan 23, 2020
I think you should make this behaviour optional and I'd probably immediately disable it in my template Rspec configuration, because I find it so annoying when debugging that exceptions are swallowed and backtraces are not printed.
JonRowe commentedon Jan 23, 2020
As I said, open to improving this if you want to work on something better, but current behaviour needs to be preserved by default :)
ioquatix commentedon Jan 23, 2020
Okay, I'll make a PR.
ioquatix commentedon Apr 24, 2020
rspec/rspec-core#2722
Here is the PR, can you please check it? Thanks.