Skip to content

Commit cb5a852

Browse files
samuel-williams-shopifyioquatix
authored andcommitted
Add SIGTERM regression test for Hybrid fork interrupt handling
SIGINT and SIGTERM are intentionally equivalent: both are trapped in the fork and converted into Interrupt (see Forked::Child.fork), so a single signal of either kind must drain the inner threads and exit rather than respawning them (issue #58). Refactors the existing single-SIGINT test into a shared helper and exercises both :INT and :TERM, locking in the documented equivalence.
1 parent 3c11ab5 commit cb5a852

1 file changed

Lines changed: 16 additions & 5 deletions

File tree

test/async/container/hybrid.rb

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,14 @@ def instance.ready!
6363
end
6464

6565
# https://github.com/socketry/async-container/issues/58
66-
it "exits the fork on a single interrupt even when the inner container has restart: true" do
66+
#
67+
# SIGINT and SIGTERM are intentionally equivalent: both are trapped in the fork and converted into `Interrupt` (see `Forked::Child.fork`), so a single signal of either kind must drain the inner threads and exit, rather than respawning them forever (the inner container has `restart: true`, the default for `async-service` managed services).
68+
def exits_fork_on_single_signal(signal)
6769
pids = IO.pipe
68-
70+
fork_pid = nil
71+
exited = false
6972
container = subject.new
73+
7074
container.run(count: 1, forks: 1, threads: 1, restart: true) do |instance|
7175
pids.last.puts(Process.pid.to_s)
7276
instance.ready!
@@ -77,11 +81,10 @@ def instance.ready!
7781

7882
fork_pid = Integer(pids.first.gets)
7983

80-
# Mimic a single SIGINT delivered to the fork (e.g. memory-based worker recycling):
81-
Process.kill(:INT, fork_pid)
84+
# Mimic a single signal delivered to the fork (e.g. memory-based worker recycling):
85+
Process.kill(signal, fork_pid)
8286

8387
# The fork must drain its inner threads and exit, rather than respawning them forever:
84-
exited = false
8588
8.times do
8689
reaped, _status = Process.waitpid2(fork_pid, Process::WNOHANG)
8790
if reaped
@@ -100,4 +103,12 @@ def instance.ready!
100103
container&.stop
101104
pids&.each(&:close)
102105
end
106+
107+
it "exits the fork on a single SIGINT even when the inner container has restart: true" do
108+
exits_fork_on_single_signal(:INT)
109+
end
110+
111+
it "exits the fork on a single SIGTERM even when the inner container has restart: true" do
112+
exits_fork_on_single_signal(:TERM)
113+
end
103114
end if Async::Container.fork?

0 commit comments

Comments
 (0)