paddybyers / node

evented I/O for v8 javascript
http://nodejs.org/
Other
91 stars 24 forks source link

SIGCHLD handling #18

Open paddybyers opened 12 years ago

paddybyers commented 12 years ago

With multiple event loops, SIGCHLD handling - specifically, the ability to be notified of the exit of a process that you have spawned - does not work. Currently node installs a SIGCHLD handler that causes callbacks to run in the default event loop. This reaps processes and notifies any child_watchers registered for the process in question.

The issues we have with this in the (library + multiple loop) case are:

Before discussing how to address this, it is important first to decide some requirements questions:

So, then what are the possible solutions?

1 Do nothing. If someone wants to spawn child processes, then this must be done from the default loop. Isolates that are fork()ed cannot spawn children. This is a pretty poor option but is achievable.

2 Continue to use SIGCHLD. When operating as a library, just impose a constraint that we have to be able to register a SIGCHLD handler. This is not an option on Android - so it would mean that such environments cannot spawn(). This is not a showstopper necessarily but would then require children to be spawned using Android's own (java) Runtime.exec() family of APIs.

If using SIGCHLD still, there is still the question of how to deliver events to non-default event loops. I think there are two options:

2a handle the event in the default loop - requiring it to outlive all other loops - decide which event loop it should be handled by, and send an async event to that loop; or

2b have a reaper thread that lives forever but is not associated with any event loop. In this thread, reap the child and then send an async event to the to event loop that must handle the lifecycle indications for that child.

I would be inclined to go for 2b but welcome input.

3 Use an alternative means to detect child exit. There might be other solutions, but one possible approach is to create a socketpair at the time the child is spawned, with one end open in the parent, and the other end open in the child - in the same way as with the signal_pipe now. Once the child exits, the parent's end will become readable (with an EOF), and this event can be handled naturally in the event loop that spawned the child.

The limitations of this approach are:

Nonetheless this is a possible option for the case where SIGCHLD is definitely not available.

The changes are prototyped here:

https://github.com/paddybyers/node/commit/8ab2dfc27976383ad92268764d60fff7bfa2c16c

paddybyers commented 12 years ago

bnoordhuis correctly spotted a problem; further change here:

https://github.com/paddybyers/node/commit/7ff0613f5c577b45a0e8db9c05e3bb680113c393