A Ruby program with multiple threads making calls to IO.popen (or indirectly via backticks) can get some nasty race
conditions if existing threads get a chance to run in the child.
This can happen, for example, if the rb_warn("Insecure world writable dir...") from file.c:path_check_0()
gets invoked in the child.
Solution is to add a call to 'rb_thread_atfork()' in the child after fork() in order to kill off those other threads.
On a related theme, it seems like the 'rb_proc_exec' in process.c:pipe_open() should be protected with rb_protect or
similar, to prevent any exceptions raised during rb_proc_exec() from being propagated to the soon-to-be-dead main thread
in the child process. I'm not familiar enough with use of rb_protect to provide a proper patch for that.
Patch attached and included inline below:
diff -ur orig/ruby/io.c ruby/io.c
--- orig/ruby/io.c 2006-06-26 08:23:47.000000000 +0100
+++ ruby/io.c 2006-07-18 22:27:33.000000000 +0100
@@ -3102,6 +3102,7 @@
retry:
switch ((pid = fork())) {
case 0: /* child */
+ rb_thread_atfork();
if (modef & FMODE_READABLE) {
close(pr[0]);
if (pr[1] != 1) {
|