On Tue, Oct 12, 2010 at 9:10 AM, Andreas Otto
<aotto1968 / users.sourceforge.net> 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
> =A0 =A0install_sighandler(SIGTERM, sighandler);
> #endif
>
> but the fork code does in "rb_fork_err"
>
> ...
> =A0 =A0for (; before_fork(), (pid =3D fork()) < 0; prefork()) {
> =A0 =A0 =A0 =A0after_fork();
> ...
> =A0 =A0after_fork();
> ...
>
> The problem is the "after_fork" is called for parent and child:
>
> #define after_fork() (GET_THREAD()->thrown_errinfo =3D 0, after_exec())
>
> #define after_exec() \
> =A0(rb_thread_reset_timer_thread(), rb_thread_start_timer_thread(),
> forked_child =3D 0, rb_disable_interrupt())
>
> void
> rb_disable_interrupt(void)
> {
> #if USE_TRAP_MASK
> =A0 =A0sigset_t mask;
> =A0 =A0sigfillset(&mask);
> =A0 =A0sigdelset(&mask, SIGVTALRM);
> =A0 =A0sigdelset(&mask, SIGSEGV);
> =A0 =A0pthread_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", $$
=3D> 1
irb(main):011:0> Got signal   2

irb(main):012:0* Signal.trap("INT", &old)
=3D> #<Proc:0x1020e154@(irb):9>
irb(main):013:0> Process.kill "INT", $$
=3D> 1
irb(main):014:0> ^C
irb(main):014:0> Process.kill "INT", $$
=3D> 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

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/