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
In reply to Complex and reliable signal handling. by vsespb
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |