From: Robert Klemme Date: 2010-10-12T16:32:29+09:00 Subject: Re: ruby bug with fork and signals (SIGTERM) On Tue, Oct 12, 2010 at 9:10 AM, Andreas Otto wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hi, > > I writing a C-Extension for ruby using "rb_fork(0,0,0,Qnil)" to create a > new process. > > Behaviour: > > 1) before fork a SIGTERM send to the parent terminate the parent > 2) after fork a SIGTERM is ignored Only in the parent? > Analyze: > > SIGTERM is initialized in "Init_signal" using > > #ifdef SIGTERM >    install_sighandler(SIGTERM, sighandler); > #endif > > but the fork code does in "rb_fork_err" > > ... >    for (; before_fork(), (pid = fork()) < 0; prefork()) { >        after_fork(); > ... >    after_fork(); > ... > > The problem is the "after_fork" is called for parent and child: > > #define after_fork() (GET_THREAD()->thrown_errinfo = 0, after_exec()) > > #define after_exec() \ >  (rb_thread_reset_timer_thread(), rb_thread_start_timer_thread(), > forked_child = 0, rb_disable_interrupt()) > > void > rb_disable_interrupt(void) > { > #if USE_TRAP_MASK >    sigset_t mask; >    sigfillset(&mask); >    sigdelset(&mask, SIGVTALRM); >    sigdelset(&mask, SIGSEGV); >    pthread_sigmask(SIG_SETMASK, &mask, NULL); > #endif > } > > and all signals are blocked except SIGVTALRM and SIGSEGV > > after adding > > sigdelset(&mask, SIGTERM); > > to rb_disable_interrupt the code is working but a real solution should > save the initial mask and later on enable the mask again ... I doubt it is a good idea to use regular signal handling code to do this. If at all you should probably use Ruby's methods. Note that you get the old signal handler back when trapping: irb(main):010:0> Process.kill "INT", $$ => 1 irb(main):011:0> Got signal 2 irb(main):012:0* Signal.trap("INT", &old) => # irb(main):013:0> Process.kill "INT", $$ => 1 irb(main):014:0> ^C irb(main):014:0> Process.kill "INT", $$ => 1 irb(main):015:0> ^C I don't know your specific requirements but in Ruby you would probably do fork do # whatever client code end Signal.trap 'TERM' do $stderr.puts "Ignoring SIGTERM" end Does that help? Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/