arya/bluepill — pull request #130 by blt04 (2012-02-02 19:41:15+00:00)
Title: Ensure socket connections are closed after exec

With bluepill 0.0.52, sometimes I receive a `Socket Timeout: Server may not be responding` error (after retrying 5 times) when trying to restart a process group. As far as I can tell, this seems to be related to restarting the delayed job daemon. It appears the `delayed_job restart` command daemonizes, keeping a copy of the Bluepill client connection open. This prevents the bluepill client connection from closing, thus blocking the client until a timeout occurs.

I'm not 100% sure this is what is happening, but regardless the attached pull request fixes the problem for me:

This pull request sets the `FD_CLOEXEC` file descriptor on each server connection. This causes the socket connection to be automatically closed if the server uses any of the `exec` family of functions (exec, system, etc.).

Normally when forking a process, the new process receives a copy of all open file descriptors. If a bluepill command (such as restart) executes a system call that forks and runs for a long time, the bluepill client connection remains open in the forked process even after the bluepill server closes the connection. This causes the bluepill client's `socket.read` call to block forever, eventually timing out and raising a `Socket Timeout: Server may not be responding` error.

Setting `close_on_exec` causes new processes to automatically close the socket connection, thus preventing this error.

For more information, see:
http://wwwwbs.cs.tu-berlin.de/user-taipan/kraxel/gnuinfo/libc/Descriptor_Flags.html
http://stackoverflow.com/questions/3179619/prevent-fork-from-copying-sockets

Also, it looks this will most likely be the default in Ruby 2.0:
http://bugs.ruby-lang.org/issues/5041