vsespb has asked for the wisdom of the Perl Monks concerning the following question:
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)
orpanic: 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.
orpanic: fold_constants JMPENV_PUSH returned 2 at /usr/local/share/perl/ +5.10.1/Net/HTTP/Methods.pm line 596.
or if I try to modify this code, it works a bit better, but I still see errors sometimes. Also sometimes Segfault happening.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.
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
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Complex and reliable signal handling.
by shmem (Chancellor) on May 31, 2013 at 18:40 UTC | |
by vsespb (Chaplain) on May 31, 2013 at 19:30 UTC | |
by vsespb (Chaplain) on May 31, 2013 at 19:39 UTC | |
|
Re: Complex and reliable signal handling.
by Anonymous Monk on May 31, 2013 at 20:23 UTC | |
by locked_user sundialsvc4 (Abbot) on May 31, 2013 at 20:24 UTC | |
by BrowserUk (Patriarch) on May 31, 2013 at 20:45 UTC | |
by vsespb (Chaplain) on May 31, 2013 at 20:57 UTC | |
by locked_user sundialsvc4 (Abbot) on Jun 01, 2013 at 13:56 UTC | |
by Anonymous Monk on Jun 02, 2013 at 00:32 UTC | |
by vsespb (Chaplain) on Aug 17, 2013 at 15:47 UTC |