Would you have time to turn that into a (tested ;) ) patch?
With attached patch on top of 1.9.3~preview1+svn33077-3
"make test"
#244 test_fork.rb:51:in `<top (required)>':
a = []
trap(:INT) { a.push(1) }
trap(:TERM) { a.push(2) }
pid = $$
begin
fork do
sleep 0.5
Process.kill(:INT, pid)
Process.kill(:TERM, pid)
end
sleep 1
a.sort
rescue NotImplementedError
[1, 2]
end
#=> "[]" (expected "[1, 2]") [ruby-dev:44005] [Ruby 1.9 - Bug #4950]
#934 test_thread.rb:389:in `<top (required)>':
open("zzz.rb", "w") do |f|
f.puts <<-END
begin
m = Mutex.new
Thread.new { m.lock; sleep 1 }
sleep 0.3
parent = Thread.current
Thread.new do
sleep 0.3
begin
fork { GC.start }
rescue Exception
parent.raise $!
end
end
m.lock
pid, status = Process.wait2
$result = status.success? ? :ok : :ng
rescue NotImplementedError
$result = :ok
end
END
end
require "./zzz.rb"
$result
#=> "" (expected "ok")
FAIL 2/937 tests failed
make: *** [yes-btest-ruby] Error 1
--- ruby1.9.1-1.9.3~preview1+svn33077.orig/thread_pthread.c
+++ ruby1.9.1-1.9.3~preview1+svn33077/thread_pthread.c
@@ -1045,6 +1045,36 @@ static pthread_t timer_thread_id;
static int timer_thread_pipe[2] = {-1, -1};
static int timer_thread_pipe_owner_process;
+#if 0
+static inline int
+timer_thread_running() {
+ return timer_thread_pipe_owner_process == getpid() ? 1 : 0;
+}
+
+static inline void timer_thread_set() {
+ timer_thread_pipe_owner_process = getpid();
+}
+
+RUBY_FUNC_EXPORTED
+void timer_thread_child_at_fork() {
+};
+
+#else
+static inline int
+timer_thread_running() {
+ return timer_thread_pipe_owner_process;
+}
+
+static inline void timer_thread_set() {
+ timer_thread_pipe_owner_process = 1;
+}
+
+RUBY_FUNC_EXPORTED
+void timer_thread_child_at_fork() {
+ timer_thread_pipe_owner_process = 0;
+};
+#endif
+
#define TT_DEBUG 0
#define WRITE_CONST(fd, str) (void)(write((fd),(str),sizeof(str)-1)<0)
@@ -1056,7 +1086,7 @@ rb_thread_wakeup_timer_thread(void)
ssize_t result;
/* already opened */
- if (timer_thread_pipe_owner_process == getpid()) {
+ if (timer_thread_running()) {
const char *buff = "!";
retry:
if ((result = write(timer_thread_pipe[1], buff, 1)) <= 0) {
@@ -1199,7 +1229,7 @@ rb_thread_create_timer_thread(void)
#endif
/* communication pipe with timer thread and signal handler */
- if (timer_thread_pipe_owner_process != getpid()) {
+ if (!timer_thread_running()) {
if (timer_thread_pipe[0] != -1) {
/* close pipe of parent process */
close_communication_pipe();
@@ -1229,7 +1259,7 @@ rb_thread_create_timer_thread(void)
#endif /* defined(HAVE_FCNTL) && defined(F_GETFL) && defined(F_SETFL) */
/* validate pipe on this process */
- timer_thread_pipe_owner_process = getpid();
+ timer_thread_set();
}
/* create timer thread */
--- ruby1.9.1-1.9.3~preview1+svn33077.orig/main.c
+++ ruby1.9.1-1.9.3~preview1+svn33077/main.c
@@ -21,6 +22,8 @@
RUBY_GLOBAL_SETUP
+extern void timer_thread_child_at_fork();
+
int
main(int argc, char **argv)
{
@@ -31,6 +34,10 @@ main(int argc, char **argv)
setlocale(LC_CTYPE, "");
#endif
+#if 1
+ pthread_atfork(NULL, NULL, timer_thread_child_at_fork);
+#endif
+
ruby_sysinit(&argc, &argv);
{
RUBY_INIT_STACK;