Home > Archive > PERL Beginners > September 2004 > SIGZERO
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
| Errin Larsen 2004-09-24, 3:59 pm |
| Hi Perlers,
I'm trying to check on the status of a process by sending a SIGZERO to
it with kill(). This SHOULD (according to the docs I've been reading)
return false if the process died. But mine is not. It always returns
true.
if( kill 0 => $pid ) {
print "the process is OK\n";
} else {
print "Something happened to the process: $!\n";
}
And for me, the above ALWAYS returns true. I'm wondering if this is
something to do with Solaris, and not Perl. Maybe this signal doesn't
behave the same way under Solaris?
Ok,
In the middle of writing this email I decided to write up a quick and
dirty test:
#!/usr/bin/perl
use warnings;
use strict;
my $pid = shift;
if( kill 0 => $pid ) {
print "Everything's ok\n";
} else {
print "$pid is not ok: $!\n";
}
When I run this code against a made up PID (I grep for it first to be
sure it's not really there), It works as expected, and:
17455 is not ok: No such process
is returned! That's good! that's what I want. but when I throw it
in my larger, longer Daemon script, it doesn't do it right. Just to
give some more explaination, My script daemonizes itself:
sub daemonize {
chdir '/' or die "Can't chdir to /: $!";
open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
open STDOUT, '/dev/null' or die "Can't write to /dev/null: $!";
defined( my $pid = fork ) or die "Can't fork the monitor: $!";
exit if $pid;
setsid or die "Can't start a new session: $!";
open STDERR, '>&STDOUT' or die "Can't dup STDOUT: $!";
}
then, It starts a bunch of children, capturing all of their process ID
in a hash:
sub start_servers {
my $cmdName = shift;
defined( my $pid = fork ) or die "Can't fork the server $cmdName: $!";
if( $pid == 0 ) { # Child
chdir '/' or die "Can't chdir to /: $!";
open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
open STDOUT, '/dev/null' or die "Can't write to /dev/null: $!";
setsid or die "Can't start a new session: $!";
open STDERR, '>&STDOUT' or die "Can't dup STDOUT: $!";
exec( $cmdName );
} else { # Parent
$children{$pid} = "$cmdName";
}
}
Then, the original goes into a loop, checking the children and (for
debug purposes at the moment) just prints some status:
do {
foreach( keys %children ) {
if( kill 0 => $_ ) {
print " - $_: $children{$_} is still ok.\n";
} else {
print " * $_: $children{$_} is not responding: $!\n";
}
}
sleep 5;
} while( 1 );
But ... I always get back the TRUE response, "- 17455: ./dummy_script
is still ok.". Did I miss something?
--Errin
| |
| Ed Christian 2004-09-24, 3:59 pm |
| Errin Larsen wrote:
> Hi Perlers,
>=20
<snip>
>=20
> if( kill 0 =3D> $pid ) {
>
<snip>
Forgive me if I presume too much, but shouldn't the above be:
if( kill 0, $pid ) {
perldoc -f kill
| |
| Jenda Krynicky 2004-09-24, 3:59 pm |
| From: "Ed Christian" <edc@corp.ptd.net>
> Errin Larsen wrote:
>
> <snip>
>
>
> <snip>
>
> Forgive me if I presume too much, but shouldn't the above be:
>
> if( kill 0, $pid ) {
Those two are equivalent.
perl -MO=Deparse -e "kill 0 => $pid"
prints
kill 0, $pid;
-e syntax OK
just like
perl -MO=Deparse -e "kill 0, $pid"
Jenda
===== Jenda@Krynicky.cz === http://Jenda.Krynicky.cz =====
When it comes to wine, women and song, wizards are allowed
to get drunk and croon as much as they like.
-- Terry Pratchett in Sourcery
| |
| Errin Larsen 2004-09-24, 3:59 pm |
| On Fri, 24 Sep 2004 10:31:36 -0400, Ed Christian <edc@corp.ptd.net> wrote:
> Errin Larsen wrote:
>
> <snip>
>
>
> <snip>
>
> Forgive me if I presume too much, but shouldn't the above be:
>
> if( kill 0, $pid ) {
>
> perldoc -f kill
>
Jenda is correct. I like to think of '=>' as "The FANCY comma!!".
It's just a pretty way of typing a comma for just such an occasion
when you want you code to reflect what you're doing. So, in the
above, I'm sending a signal to $pid, so the big arrow "shows" that the
signal (0) is being sent to that process ($pid)! Perl is Fun!!!
This works great (and is seen most often) in hash declarations:
my %demo_hash = (
Key_One => 1,
Key_Two => 2,
Key_Three => 3
);
| |
| Ed Christian 2004-09-24, 3:59 pm |
| Errin Larsen wrote:
> On Fri, 24 Sep 2004 10:31:36 -0400, Ed Christian <edc@corp.ptd.net>
> wrote:=20
>=20
> Jenda is correct. I like to think of '=3D>' as "The FANCY comma!!".
> It's just a pretty way of typing a comma for just such an occasion
> when you want you code to reflect what you're doing. So, in the
> above, I'm sending a signal to $pid, so the big arrow "shows" that
> the signal (0) is being sent to that process ($pid)! Perl is Fun!!!=20
>=20
> This works great (and is seen most often) in hash declarations:
>=20
> my %demo_hash =3D (
> Key_One =3D> 1,
> Key_Two =3D> 2,
> Key_Three =3D> 3
> );
I stand corrected. Sorry it wasn't an easy solution. :)
| |
| Errin Larsen 2004-09-24, 3:59 pm |
| Ok, I learned something else ...
When I type:
kill -9 <SOME_PROCESS_ID>
on the command line, It's not actually killing the process.
Let me explain. My script starts 3 others and then stays around
watching them. So, when I run it, I get this:
# ps -ef | grep dummy
user1 18000 1 0 10:04:22 ? 0:00 dummy_monitor
user1 18001 18000 0 10:04:22 ? 0:00 dummy1
user1 18002 18000 0 10:04:22 ? 0:00 dummy2
user1 18003 18000 0 10:04:22 ? 0:00 dummy3
(the names have been changed to protect the innocent!)
Now ... After I run a kill:
# kill -9 18002
# ps -ef | grep dummy
user1 18000 1 0 10:04:22 ? 0:00 dummy_monitor
user1 18001 18000 0 10:04:22 ? 0:00 dummy1
user1 18003 18000 0 10:04:22 ? 0:00 dummy3
However, I just discovered that if I check the PID instead:
# ps -ef | grep 18002
user1 180002 18000 0 0:00 <defunct>
See that "<defunct>"?! How did my process get a <defunct> status? Is
that a Solaris-fancy way of saying "zombie-child"? The above explains
why my (kill 0 => $pid) isn't working the way I expect, but How can I
kill the kid. The <defunct> child process finally dies if I kill the
parent (original dummy_monitor) script. Does this mean that my setsid
line in my original script is not working correctly? I'm 
here.
--Errin
| |
| Jenda Krynicky 2004-09-24, 3:59 pm |
| From: Errin Larsen <errinlarsen@gmail.com>
> See that "<defunct>"?! How did my process get a <defunct> status? Is
> that a Solaris-fancy way of saying "zombie-child"?
I believe so.
> The above explains
> why my (kill 0 => $pid) isn't working the way I expect, but How can I
> kill the kid. The <defunct> child process finally dies if I kill the
> parent (original dummy_monitor) script. Does this mean that my setsid
> line in my original script is not working correctly? I'm 
> here.
I believe you are supposed to wait()/waitpid() on your children. Or
install a $SIG{SIGCHLD} handler that reaps the children.
I haven't used Perl under any Unix for years so I can't give you the
details. perldoc perlipc should help.
Jenda
===== Jenda@Krynicky.cz === http://Jenda.Krynicky.cz =====
When it comes to wine, women and song, wizards are allowed
to get drunk and croon as much as they like.
-- Terry Pratchett in Sourcery
| |
| Errin Larsen 2004-09-24, 3:59 pm |
| On Fri, 24 Sep 2004 17:20:44 +0200, Jenda Krynicky <jenda@krynicky.cz> wrote:
> From: Errin Larsen <errinlarsen@gmail.com>
>
> I believe so.
>
>
> I believe you are supposed to wait()/waitpid() on your children. Or
> install a $SIG{SIGCHLD} handler that reaps the children.
>
> I haven't used Perl under any Unix for years so I can't give you the
> details. perldoc perlipc should help.
>
>
>
> Jenda
Yup. I tried putting:
$SIG{CHLD}='IGNORE';
in my parent and that prevents the zombie child. So, next question!
how do I wait() or waitpid() on more than one process? don't both of
those make the wait()ing process sit still and do nothing else until
it gets a return? I'll read perlipc again (man that's a hard one to
grok) and see what it says.
--Errin
| |
| Wiggins d Anconia 2004-09-24, 3:59 pm |
| > From: Errin Larsen <errinlarsen@gmail.com>
>
> I believe so.
I do as well.
>
>
> I believe you are supposed to wait()/waitpid() on your children. Or
> install a $SIG{SIGCHLD} handler that reaps the children.
>
That is what i was thinking. Essentially a process that has children
wants to hear from them (and will stop sending money if it doesn't).
Generally this is done by having the parent "wait" for the child until
it notifies the parent that it is gone, generally the parent knows that
when it doesn't have any more children it is done (or is to spawn more,
etc.).
> I haven't used Perl under any Unix for years so I can't give you the
> details. perldoc perlipc should help.
>
Yes, as well as,
perldoc -f wait
perldoc -f waitpid
> Jenda
http://danconia.org
| |
| Errin Larsen 2004-09-24, 3:59 pm |
| On Fri, 24 Sep 2004 10:34:50 -0500, Errin Larsen <errinlarsen@gmail.com> wrote:
> On Fri, 24 Sep 2004 17:20:44 +0200, Jenda Krynicky <jenda@krynicky.cz> wrote:
<<SNIP>>
[color=darkred]
>
> how do I wait() or waitpid() on more than one process? don't both of
> those make the wait()ing process sit still and do nothing else until
> it gets a return? I'll read perlipc again (man that's a hard one to
> grok) and see what it says.
>
> --Errin
>
Well, I found the following code snippet in perlipc:
sub REAPER {
my $child;
while( ( $child = waitpid( -1, WNOHANG ) ) > 0 ) {
$Kid_Status{$child} = $?;
}
$SIG{CHLD} = \&REAPER;
}
$SIG{CHLD} = \&REAPER;
This seems to do something similar to what I want, but I'm 
about exactly what it's doing. what does the '-1' argument to
waitpid() do? What is the 'WNOHANG' flag? Why are we reassigning
'$SIG{CHLD}' to 'REAPER' inside of REAPER (this seems redundant to
me!)
I realize this is getting away from the "beginner" focus of this
mailing list, but I don't currently belong to any other mailing lists.
Thanks for any help you can throw at me.
--Errin
| |
| DBSMITH@OhioHealth.com 2004-09-24, 3:59 pm |
| I am a beginner, but I love to see all the knowledge transfer so keep the
moderate to difficult questions coming!
thanks,
Derek B. Smith
OhioHealth IT
UNIX / TSM / EDM Teams
614-566-4145
Errin Larsen <errinlarsen@gmail.com>
09/24/2004 11:44 AM
Please respond to Errin Larsen
To: Jenda Krynicky <jenda@krynicky.cz>
cc: beginners@perl.org
Subject: Re: SIGZERO
On Fri, 24 Sep 2004 10:34:50 -0500, Errin Larsen <errinlarsen@gmail.com>
wrote:
> On Fri, 24 Sep 2004 17:20:44 +0200, Jenda Krynicky <jenda@krynicky.cz>
wrote:
<<SNIP>>
[color=darkred]
>
> how do I wait() or waitpid() on more than one process? don't both of
> those make the wait()ing process sit still and do nothing else until
> it gets a return? I'll read perlipc again (man that's a hard one to
> grok) and see what it says.
>
> --Errin
>
Well, I found the following code snippet in perlipc:
sub REAPER {
my $child;
while( ( $child = waitpid( -1, WNOHANG ) ) > 0 ) {
$Kid_Status{$child} = $?;
}
$SIG{CHLD} = \&REAPER;
}
$SIG{CHLD} = \&REAPER;
This seems to do something similar to what I want, but I'm 
about exactly what it's doing. what does the '-1' argument to
waitpid() do? What is the 'WNOHANG' flag? Why are we reassigning
'$SIG{CHLD}' to 'REAPER' inside of REAPER (this seems redundant to
me!)
I realize this is getting away from the "beginner" focus of this
mailing list, but I don't currently belong to any other mailing lists.
Thanks for any help you can throw at me.
--Errin
--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
<http://learn.perl.org/> <http://learn.perl.org/first-response>
| |
| Wiggins d Anconia 2004-09-24, 3:59 pm |
| > On Fri, 24 Sep 2004 10:34:50 -0500, Errin Larsen
<errinlarsen@gmail.com> wrote:
<jenda@krynicky.cz> wrote:[color=darkred]
>
> <<SNIP>>
>
>
>
> Well, I found the following code snippet in perlipc:
>
> sub REAPER {
> my $child;
> while( ( $child = waitpid( -1, WNOHANG ) ) > 0 ) {
> $Kid_Status{$child} = $?;
> }
> $SIG{CHLD} = \&REAPER;
> }
> $SIG{CHLD} = \&REAPER;
>
> This seems to do something similar to what I want, but I'm 
> about exactly what it's doing. what does the '-1' argument to
> waitpid() do? What is the 'WNOHANG' flag? Why are we reassigning
> '$SIG{CHLD}' to 'REAPER' inside of REAPER (this seems redundant to
> me!)
>
The -1 argument is to tell C<waitpid> that it should wait for any
processes in the session, aka all of your children as opposed to a
particular PID. The C<WNOHANG> flag tells waitpid not to block if no
processes are available to reap, aka allow the parent to continue
processing something else. The reassignment appears to be to avoid a
bug in older systems that use a SysV fork model, perldoc perlipc
includes a comment about this.
"Because Perl's signal mechanism is currently based on the signal(3)
function from the C library, you may sometimes be so misfortunate as to
run on systems where that function is "broken", that is, it behaves in
the old unreliable SysV way rather than the newer, more reasonable BSD
and POSIX fashion."
Followed by an example of a defensive signal handler.
> I realize this is getting away from the "beginner" focus of this
> mailing list, but I don't currently belong to any other mailing lists.
> Thanks for any help you can throw at me.
>
> --Errin
>
I still suggest checking out the POE framework, specifically the
POE::Wheel::Run to handle all of this nonsense. At least once you are
satisfied that you understand the underpinnings.
http://danconia.org
| |
| Errin Larsen 2004-09-24, 3:59 pm |
| On Fri, 24 Sep 2004 11:52:19 -0400, dbsmith@ohiohealth.com
<dbsmith@ohiohealth.com> wrote:
> I am a beginner, but I love to see all the knowledge transfer so keep the
> moderate to difficult questions coming!
>
<<SNIP>>
I'm like you, Derek! I love just reading this stuff. Satisfies some
inner-g need I have!
>
> On Fri, 24 Sep 2004 10:34:50 -0500, Errin Larsen <errinlarsen@gmail.com>
> wrote:
> wrote:
>
> <<SNIP>>
>
<<SNIP>>
> This seems to do something similar to what I want, but I'm 
> about exactly what it's doing. what does the '-1' argument to
> waitpid() do? What is the 'WNOHANG' flag? Why are we reassigning
> '$SIG{CHLD}' to 'REAPER' inside of REAPER (this seems redundant to
> me!)
>
<<SNIP>>
Ok, I found this is the Perl Cookbook. Below is a quote:
" To avoid accumulating dead children, simply tell the system that
you're not interested in them by setting $SIG{CHLD} to "IGNORE". If
you want to know which children die and when, you'll need to use
waitpid.
The waitpid function reaps a single process. Its first argument is the
process to wait for - use -1 to mean any process - and its second
argument is a set of flags. We use the WNOHANG flag to make waitpid
immediately return 0 if there are no dead children. A flag value of 0
is supported everywhere, indicating a blocking wait. Call waitpid from
a SIGCHLD handler, as we do in the Solution, to reap the children as
soon as they die.
The wait function also reaps children, but it does not have a
non-blocking option. If you inadvertently call it when there are
running child processes but none have exited, your program will pause
until there is a dead child. "
Now, why can't the {perldoc -f waitpid} tell me "use -1 to mean any
process" ?!? That would have been helpful!!
--Errin
|
|
|
|
|