Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions test/async/container/hybrid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,14 @@ def instance.ready!
end

# https://github.com/socketry/async-container/issues/58
it "exits the fork on a single interrupt even when the inner container has restart: true" do
#
# 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).
def exits_fork_on_single_signal(signal)
pids = IO.pipe

fork_pid = nil
exited = false
container = subject.new

container.run(count: 1, forks: 1, threads: 1, restart: true) do |instance|
pids.last.puts(Process.pid.to_s)
instance.ready!
Expand All @@ -77,11 +81,10 @@ def instance.ready!

fork_pid = Integer(pids.first.gets)

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

# The fork must drain its inner threads and exit, rather than respawning them forever:
exited = false
8.times do
reaped, _status = Process.waitpid2(fork_pid, Process::WNOHANG)
if reaped
Expand All @@ -100,4 +103,12 @@ def instance.ready!
container&.stop
pids&.each(&:close)
end

it "exits the fork on a single SIGINT even when the inner container has restart: true" do
exits_fork_on_single_signal(:INT)
end

it "exits the fork on a single SIGTERM even when the inner container has restart: true" do
exits_fork_on_single_signal(:TERM)
end
end if Async::Container.fork?
Loading