Re: Questions about perl daemons with child processes and open files / signals
- From: xhoster@xxxxxxxxx
- Date: 06 Apr 2006 16:05:05 GMT
"none" <mikem891@xxxxxxxxxxx> wrote:
Hi, I have some questions about perl codes
running as daemon which launch a child process.
I need to run a perl script as a daemon. The
script will monitor tcpdump's output. At first
my script was using a temp file to store the
tcpdump output, but I decided to use a pipe
instead (and did not want to run my script piped
on the command line: tcpdump | ./foo . I wanted
to include the pipe to tcpdump in the script).
The best way I found to do this is by creating
a child process for tcpdump, because running:
open LOGTMPFILE, "tcpdump -i ne1 2> /dev/null |";
do not return the control to the script until
tcpdump terminated. I'm doing it in starttcpdump()
and it works very well, but I'm not sure that
it's the best way to do this.
You say that that open doesn't return control to the script (which I can
not replicate on my machine) yet that open is exactly what you use in
starttcpdump(). Are you saying it does return control when used in the
child, but not when used in the parent?
Another thing I wanted is to be able to call
my script like this to terminated the running
daemon:
~$ foo stop
Here I have a problem, what I planned to do
was catching signals in the script to make some
cleanup before terminating the script:
- kill the child process
- close the tcpdump open pipe (LOGTMPFILE)
Since the pipe is open in the child process, killing the child
will automatically close the pipe.
if I don't do this, tcpdump continues to run
when the script ends.
tcpdump should exit when it realizes that the child is no longer listening
to it. On my machine, it takes a few seconds for it to realize this
(I think what happens is that it doesn't realize no one is listening until
it fills up one pipe buffer.) One way to speed up this death is to record
the pid of the tcpdump process (returned by the "open" command) and
explicitly kill it.
$ perl -le 'my $pid=open my $fh, "/usr/sbin/tcpdump |" or die $!; \
foreach (1..10) { print scalar <$fh>}; kill 13, $pid; \
close $fh or die "Died with $\! ", $\!+0, " $?"'
In your case, of course, you would have to record the pid so that it could
killed from the signalhandler.
The problem I have is
that only the child process can close the
LOGTMPFILE file. So I tought I should kill the
child process first (which close the tcpdump
pipe) and then ask the child process to close
the parent process.
Why is there a parent process at all at this point? The parent doesn't
seem to have anything useful to do, so why not exit rather than hanging
around in a waitpid?
I also tried to close the
parent process, thinking it would automatically
close the child and tcpdump pipe. but it does
not work. Everything I tried seems to hang at
close LOGTMPFILE and never give back the control
to the script.
So it hangs upon the open if you don't fork and upon the close if you
do fork? What OS are you using?
The best I was able to get, is have both instances
of perl (parent and child) killed, but tcpdump
still running. By the way it seems to work well
if I press CTRL-C will running the script normally
(not as daemon). the tcpdump process is killed.
Here are my questions:
- I'm I doing tcpdump pipe launching the right
way? it's the best way I found to do this. But
it takes more memory (another instance of the
process). Is there a better way. I do not want
to use temp files.
I don't see what the fork in starttcpdump gets you at all. If you are
going to do it, at least have the parent exit rather than hanging around.
Then you don't need to worry about killing it.
- Is there anything wrong with my daemon mode
subroutine?
I don't know, but I do know that, for debugging purposes, you should
probably not reopen STDERR to /dev/null.
- How can I modify my code to be able to kill
everything: parent, child and tcpdump processes.
Record the pid of tcpdump, and explicitly kill it.
....
- Which signal should I use to stop the script?
HUP, INT, QUIT ?
Any suggestions and tips would be greatly appreciated.
sub signalhandler
{
my $signame = shift;
# Child process
if (-e "/var/run/foo.child.pid")
That file can exist whether you are in the child or not.
{
open (PIDFILE, "/var/run/foo.pid");
my $pid = <PIDFILE>;
close (PIDFILE);
close (LOGTMPFILE); # Close the tcpdump pipe
kill INT => $pid; # Kill the parent process
unlink("/var/run/foo.child.pid");
You have a race condition here. The parent gets killed, which activates
this very same subroutine but in that parent process, then you unlink the
file whose existence is supposed to signal that we are in the child. So
if the killed parent gets to the file test before the child gets to the
unlink, the parent will think it is the child. I don't really know what
that will cause to happen.
Xho
--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
.
- Follow-Ups:
- References:
- Prev by Date: Re: Apache/PHP 5.1.2/mod_perl Solaris 10 Problem
- Next by Date: Re: Find duplicates in a dat file "Att Xicheng"
- Previous by thread: Re: Questions about perl daemons with child processes and open files / signals
- Next by thread: Re: Questions about perl daemons with child processes and open files / signals
- Index(es):
Relevant Pages
|