From: Eric Wong Date: 2014-05-14T19:28:00+00:00 Subject: [ruby-core:62590] Re: [ruby-trunk - Bug #9835] IGNORE signal handler has possible race condition in Ruby 2.1.2 It looks like a race condition in your code. You were lucky to not hit it in 1.8.7 or with a different use of trap (because execution speeds may be different different). parent execution timeline -----------------------------+ trap(USR1, show_children) | | fork ------------------------+-- child execution timeline ----- | *** kill(USR1, -getpgid($$)) | trap(USR1, IGNORE) | Once you fork, parent and child run in parallel. So the order of execution where '***' is highlighted is outside your control. So to ensure your child ignores properly, you must setup the ignore handler before forking. There will always be a moment in time where the parent and child will have the same signal handler. You also do not want to a signal in the parent which arrive immediately before or after the fork, either. So I suggest something like the following to defer signals in the parent: # note: this count nals in general) is racy usr1_queue = [] show_children = trap("USR1") { usr1_queue << nil } # defer signals pid = fork if pid # parent trap("USR1", show_children) # restore immediate handling # process deferred signals usr1_queue.each { show_children.call } usr1_queue.clear ... else # child trap("USR1", "IGNORE") # do nothing with usr1_queue here, implicitly ignored ... end