Fix for spawning subprocesses with fork_worker option #2267
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
This fixes a bug in
fork_worker
mode (#2099) where an application that spawns subprocesses can sometimes getnil
instead of an expectedProcess::Status
object when waiting on the child (see #2099 (comment)).test_fork_worker_spawn
demonstrates the regression and currently fails onmaster
:puma/test/test_integration_cluster.rb
Lines 171 to 183 in 2d9b72e
This PR is one of two approaches for a fix- it stores the list of forked worker pids and the
SIGCHLD
handler calls non-blockingProcess.wait
on each of them, removing the pids that have exited. This is similar to#wait_workers
.Worth noting that this approach results in a
wait
syscall for every worker for every subprocess spawned by worker 0's application, which might cause some performance impact for applications which spawn lots of subprocesses and/or have a large number of workers. (I haven't benchmarked in detail so I don't know if it really matters or how big an impact it might be.)An alternative approach (aacd629) avoids a
SIGCHLD
handler and instead spawns a separate thread for each forked worker that calls blockingProcess.wait
, to automatically clean up each process as it exits. This is similar toProcess.detach
- it avoids the extra syscall per worker * subprocess, at the cost of an extra thread per worker. That approach was discouraged in #2099 (comment) but I thought worth mentioning in any case.Your checklist for this pull request
[changelog skip]
the pull request title.[ci skip]
to the title of the PR.#issue
" to the PR description or my commit messages.