Ruby bug with fork and signals (SIGTERM)

-----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

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 …

mfg

Andreas O.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.15 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJMtAi8AAoJEGTcPijNG3/A2s0H/iRGL+1iWvOyxS6fbuEBsWx5
1I0/4IwGVWy40HpwfS+gQ1vZiAK5y9M30FQQqrtiekD1G/12STT0FSuSKFgAE6Y6
KEyCS8SILpVDlAxdVQRlFEyO+BdVPRunJSfnDhyglyqRKmG5QbTHbDrsX0GtI+2c
Ilh8HlAV9MVRzfTUAsPl6s7kK5pvEC82cxl8suEkdpoL6huhXxnfwzdGDBHx8oKE
gEDWY1knMAxc5KrBY2XO4yKuImCivl8KgRz6knryaVNntrjuiIw2DtVXopRBuxFz
EL6ylWQXNJlxPHihkKAVdVzo67oON+olnK2spC8msfTAz4TNjQpVapJasem8id4=
=YUmn
-----END PGP SIGNATURE-----

On Tue, Oct 12, 2010 at 9:10 AM, Andreas O.
[email protected] wrote:

  1. before fork a SIGTERM send to the parent terminate the parent
  2. after fork a SIGTERM is ignored

Only in the parent?


#define after_exec()
sigdelset(&mask, SIGSEGV);
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)
=> #Proc:0x1020e154@:9(irb)
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

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Am 12.10.2010 09:32, schrieb Robert K.:

Behaviour:

  1. before fork a SIGTERM send to the parent terminate the parent
  2. after fork a SIGTERM is ignored

Only in the parent?

I just test the parent.

sigdelset(&mask, SIGVTALRM);

fork do

whatever client code

end

Signal.trap ‘TERM’ do
$stderr.puts “Ignoring SIGTERM”
end

Does that help?

My problem is just the opposite

I want that SIGTERM is not ignored …
the original parent does end on SIGTERM
the parent after fork does not stop on SIGTERM

mfg, Andreas O.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.15 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJMtEKEAAoJEGTcPijNG3/AVBwH/108Gs9xoKoFg92lrIZ0sGQM
EicxDgJ5hzK5M5PAM+agsKaq7Yrq4F3YcbY9TawmoetfTJ8rhyyvBAqAiXXc/jjk
ngR3+Yym7KOSXTZBskGXzwk7eqg5uPM+iufGcv7qVoBT/OhtRIfylbD2M+AMkf5U
U2wO4ZwSwEiI5SxUTm/jffJ4VKkF4MCw6XoDdgImkUsvyZswXjUhqlZy8pyePAl/
BIutY2A0oTprAXEhM3W+JnWsRzaB8Y8cnJu7KTTHKhF0EDW/tdzGetNHa0K08XFV
e/ODkJOQ/id5hDlIuj0LgWkIWpuoKvCNSH3ZixjFweGcV62m2DdPgkTbY0fM22s=
=S+jo
-----END PGP SIGNATURE-----