I have fork()'ing application with one parent process and multiple children processes. It works fine, but I am having problems implementing graceful termination after SIGINT/SIGHUP/SIGTERM.

Requirements are:

1. I use File::Temp for temporary files (I need named temporary files). Children processes should handle SIGINT/SIGHUP, because otherwise destructors are not called and temporary files left on disk.

2. If child dies with exception, parent should handle SIGCHLD, terminate all other children and terminate itself.

3. If parent dies (either because of exception, or maybe because of SIGTERM) it should terminate all children.

Problems:

After I added signals handling to children code, I am getting errors (often or rare)

panic: fold_constants JMPENV_PUSH returned 2 at /usr/share/perl5/File/ +Temp.pm line 1015. panic: fold_constants JMPENV_PUSH returned 2 at /usr/share/perl5/File/ +Temp.pm line 1015. panic: fold_constants JMPENV_PUSH returned 2 at /usr/share/perl5/File/ +Temp.pm line 1015.
or
panic: fold_constants JMPENV_PUSH returned 2 at /usr/local/share/perl/ +5.10.1/Net/HTTP/Methods.pm line 596.
or
panic: fold_constants JMPENV_PUSH returned 2 at /usr/local/share/perl/ +5.10.1/Net/HTTP/Methods.pm line 596. panic: fold_constants JMPENV_PUSH returned 2 at /usr/local/share/perl/ +5.10.1/URI.pm line 132.
or if I try to modify this code, it works a bit better, but I still see errors sometimes. Also sometimes Segfault happening.

Children code:

my $first_time = 1; my @signals = qw/INT TERM USR2 HUP/; for my $sig (@signals) { $SIG{$sig} = sub { if ($first_time) { $first_time = 0; exit(1); # we need exit, it will call all destructors whic +h will destroy tempfiles } }; } dump_error() unless (defined eval {do_work(); 1; }); $SIG{$_} = 'IGNORE' for (@signals); # THIS CAN BE REMOVED - RESULT IS +SAME kill(POSIX::SIGUSR1, $parent_pid); # THIS CAN BE REMOVED - RESULT IS S +AME exit(1);

Parent code:

my $first_time = 1; for my $sig (qw/INT TERM CHLD USR1 HUP/) { $SIG{$sig} = sub { local ($!,$^E,$@); if ($first_time) { $first_time = 0; kill (POSIX::SIGUSR2, keys %{$self->{children}}); print STDERR "EXIT on SIG$sig\n"; exit(1); } }; } do_parent_work();

My perl version is 5.10 on linux, I understand that it's hard to test particular signal handling code on all perl versions, but I am looking for a scheme, that is reliable by design and unlikely produce bug.

Or maybe you can find bug in my above code?

p.s. I've read about sigaction() but still don't see how it can help and why


In reply to Complex and reliable signal handling. by vsespb

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.