Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > fork, exec, and signal handling

Reply
Thread Tools

fork, exec, and signal handling

 
 
Todd Pytel
Guest
Posts: n/a
 
      12-31-2003
Hi all,

An infrequent perl coder here, having some issues with signal handling.
I'm not understanding something about how forking works with signals, I
think. The script is supposed to loop, running tcpdump until it exits
(after a certain number of packets are captured), rotating the dump output
and analyzing the output with tcpstat. Since the tcpdump can be rather
lengthy, I'd like to catch TERM signals and have the output analyzed so as
not to lose data. Here's some of what I've come up with - the use of pid
files is rather ghetto, I think, so suggestions are welcome:

$SIG{'TERM'} = \&term_handler;

sub main {
while ( 1 ) {
( $stop ) && exit;
defined (my $pid = fork) or die "Cannot fork: $!";
unless ($pid) {
exec "tcpdump -c $packet_count -i $interface -w $output > /dev/null 2>&1";
}
open PIDFILE, "> $dumppid";
print PIDFILE "$pid\n";
close PIDFILE;
waitpid($pid, 0);
unlink $dumppid;
&rotate;
&analyze; # Should fork this, too - don't want to wait on analysis
}
}

sub term_handler {
print "Running term_handler...\n";
$stop = 1;
if ( -e $dumppid ) {
open PIDFILE, "$dumppid";
while (<PIDFILE>) {
chomp;
kill 15, $_;
}
close PIDFILE;
}
}

The problem is that the signal never gets caught, so the tcpdump keeps
going, and the cleanup at the end of main never occurs. From what I've
seen searching, this has something to do with the parent waiting on the
child process, but I'm not experienced enough to see exactly what the
problem is. Is there a solution or alternate approach that I can use here?

Thanks,
Todd Pytel
 
Reply With Quote
 
 
 
 
Anno Siegel
Guest
Posts: n/a
 
      01-02-2004
Todd Pytel <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> Hi all,
>
> An infrequent perl coder here, having some issues with signal handling.
> I'm not understanding something about how forking works with signals, I
> think. The script is supposed to loop, running tcpdump until it exits
> (after a certain number of packets are captured), rotating the dump output
> and analyzing the output with tcpstat. Since the tcpdump can be rather
> lengthy, I'd like to catch TERM signals and have the output analyzed so as
> not to lose data. Here's some of what I've come up with - the use of pid
> files is rather ghetto, I think, so suggestions are welcome:


Why do you think you need to store the pid in a file? Just declare
the $pid variable outside the loop and use it in term_handler().

> $SIG{'TERM'} = \&term_handler;
>
> sub main {
> while ( 1 ) {
> ( $stop ) && exit;


Why the parentheses around $stop? Also, $stop is undeclared.

> defined (my $pid = fork) or die "Cannot fork: $!";
> unless ($pid) {
> exec "tcpdump -c $packet_count -i $interface -w $output > /dev/null 2>&1";
> }
> open PIDFILE, "> $dumppid";
> print PIDFILE "$pid\n";
> close PIDFILE;
> waitpid($pid, 0);
> unlink $dumppid;
> &rotate;
> &analyze; # Should fork this, too - don't want to wait on analysis


Don't call subs with a leading "&" unless you want the effects associated
with that form.

> }
> }


[more code snipped]

Try something along these lines (untested):

$SIG{'TERM'} = \&term_handler;

main();

my $stop = 0;
my $pid;
sub main {
while ( 1 ) {
$stop && do { print "main exiting\n"; exit };
defined ($pid = fork) or die "Cannot fork: $!";
unless ($pid) {
exec "tcpdump -c $packet_count -i $interface " .
"-w $output > /dev/null 2>&1";
}
waitpid($pid, 0);
&rotate;
&analyze; # Should fork this, too - don't
# want to wait on analysis
}
}

sub term_handler {
print "Running term_handler...\n";
$stop = 1;
return unless $pid;
kill 15, $pid;
}

Anno
 
Reply With Quote
 
 
 
 
Brian McCauley
Guest
Posts: n/a
 
      01-02-2004
Todd Pytel <(E-Mail Removed)> writes:

> An infrequent perl coder here, having some issues with signal handling.
> I'm not understanding something about how forking works with signals, I
> think.


No, you are not understanding what exec() does.

exec() completely replaces the current process with a new executable.

If you set up a signal handler then exec() the signal handler no
longer exists in the new process.

This has nothing to do with Perl.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      01-02-2004
Brian McCauley <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> Todd Pytel <(E-Mail Removed)> writes:
>
> > An infrequent perl coder here, having some issues with signal handling.
> > I'm not understanding something about how forking works with signals, I
> > think.

>
> No, you are not understanding what exec() does.
>
> exec() completely replaces the current process with a new executable.
>
> If you set up a signal handler then exec() the signal handler no
> longer exists in the new process.


Well, the OP didn't explain the problem very well, but I think exec is fine
where it is. The Idea was, if I understand, to make a TERM signal to the
parent kill the child process (instead of the parent).

To the OP: Perl's system() already does something very similar -- to INTR
and TERM, as I recall, but look it up.

Anno
 
Reply With Quote
 
Charles DeRykus
Guest
Posts: n/a
 
      01-03-2004
In article <(E-Mail Removed). org>,
Todd Pytel <(E-Mail Removed)> wrote:
>...
>lengthy, I'd like to catch TERM signals and have the output analyzed so as
>not to lose data. Here's some of what I've come up with - the use of pid
>files is rather ghetto, I think, so suggestions are welcome:
>
>$SIG{'TERM'} = \&term_handler;
>
>sub main {
> while ( 1 ) {
> ( $stop ) && exit;
> defined (my $pid = fork) or die "Cannot fork: $!";
> unless ($pid) {
> exec "tcpdump -c $packet_count -i $interface -w $output > /dev/null 2>&1";
> }
> open PIDFILE, "> $dumppid";
> print PIDFILE "$pid\n";
> close PIDFILE;
> waitpid($pid, 0);
> unlink $dumppid;
> &rotate;
> &analyze; # Should fork this, too - don't want to wait on analysis
> }
>}
>
>sub term_handler {
> print "Running term_handler...\n";
> $stop = 1;
> if ( -e $dumppid ) {
> open PIDFILE, "$dumppid";
> while (<PIDFILE>) {
> chomp;
> kill 15, $_;
> }
> close PIDFILE;
> }
>}
>
>The problem is that the signal never gets caught, so the tcpdump keeps
>going, and the cleanup at the end of main never occurs. From what I've
>seen searching, this has something to do with the parent waiting on the
>child process, but I'm not experienced enough to see exactly what the
>problem is. Is there a solution or alternate approach that I can use here?
>


I'm not sure what your search revealed but I don't see how
the parent's blocking waitpid could be problematic at all.
The TERM handler below for instance gets caught:

my $pid = fork;
die $! unless defined $pid;

$SIG{ TERM } = sub { die "caught a term ..."; };
unless ($pid) {
exec "sleep 600" or die "exec failed: $!"; }
else {
waitpid( $pid,0);
}

The only long shots I can think of is that the signal's
being blocked or ignored somewhere else. You might want
to trace what's happening in the rest of the code.

hth,
--
Charles DeRykus
 
Reply With Quote
 
Todd Pytel
Guest
Posts: n/a
 
      01-04-2004
Thanks for the responses.

Yes, Brian, I'm aware that exec() replaces the current process. I'm
somewhat clueless, but not that clueless. As Charles and Anno suggested,
the problem was elsewhere. Two places, really...

1) The $SIG{'TERM'} line was defined globally, but *after* the program had
entered the main loop. Thus the signal wasn't being caught. I haven't done
signal handling before, and thought that perl "read ahead" of the loop.
Guess not.

2) The exec command included the shell redirection - "> /dev/null 2>&1".
This means the fork's pid is the pid of /bin/sh invoked to run tcpdump,
not the pid of tcpdump itself. Removing the redirection takes care of
that, which is fine since I was planning to daemonize the process anyway.

Thanks for the pushes in the right direction, and sorry if I was unclear.
All I've read is the llama book, and this is the first substantial script
I've done from scratch, as opposed to modifying other people's stuff.

--Todd
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
No Signal and Signal 'Low' MapleE. Wireless Networking 0 03-20-2010 08:32 PM
signal handling and (structured) exception handling Peter C++ 34 10-17-2009 10:03 AM
Aside from delta cycles and/or resolution functions, how can the effective value of a signal differ from a driving signal of its? Colin Paul Gloster VHDL 0 01-11-2007 01:31 PM
threading.Thread vs. signal.signal Jack Orenstein Python 0 09-17-2005 11:24 PM
Async-signal safe functions in signal handlers (unix) Michael Pronath Python 1 01-03-2005 01:10 PM



Advertisments