Professional Web Applications Themes

SIGZERO - PERL Beginners

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 ...

  1. #1

    Default SIGZERO

    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
    Errin Guest

  2. #2

    Default Re: SIGZERO

    On Fri, 24 Sep 2004 09:17:58 -0500, Errin Ln <com> wrote: 

    << SNIP >>
     

    I guess I should have pointed out that, at the OS prompt, I'm 'kill
    -9' ing one of those "dummy_script" processes so I can test what
    happens when it dies.

    --Errin
    Errin Guest

  3. #3

    Default RE: SIGZERO

    Errin Ln wrote: 

    <snip>
     

    <snip>

    Forgive me if I presume too much, but shouldn't the above be:

    if( kill 0, $pid ) {

    perldoc -f kill
    Ed Guest

  4. #4

    Default RE: SIGZERO

    From: "Ed Christian" <ptd.net> 
    >
    > <snip>

    >
    > <snip>
    >
    > Forgive me if I presume too much, but shouldn't the above be:
    >
    > if( kill 0, $pid ) {[/ref]

    Those two are equivalent.

    perl -MO=Dep -e "kill 0 => $pid"
    prints
    kill 0, $pid;
    -e syntax OK
    just like
    perl -MO=Dep -e "kill 0, $pid"

    Jenda
    ===== 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

    Jenda Guest

  5. #5

    Default Re: SIGZERO

    On Fri, 24 Sep 2004 10:31:36 -0400, Ed Christian <ptd.net> wrote: 
    >
    > <snip>

    >
    > <snip>
    >
    > Forgive me if I presume too much, but shouldn't the above be:
    >
    > if( kill 0, $pid ) {
    >
    > perldoc -f kill
    >[/ref]

    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
    );
    Errin Guest

  6. #6

    Default RE: SIGZERO

    Errin Ln wrote: 
    >>
    >> <snip>
    >>  
    >>
    >> <snip>
    >>
    >> Forgive me if I presume too much, but shouldn't the above be:
    >>
    >> if( kill 0, $pid ) {
    >>
    >> perldoc -f kill
    >> [/ref]
    >
    > 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
    > );[/ref]

    I stand corrected. Sorry it wasn't an easy solution. :)
    Ed Guest

  7. #7

    Default Re: SIGZERO

    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 confused
    here.

    --Errin
    Errin Guest

  8. #8

    Default Re: SIGZERO

    From: Errin Ln <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
    ===== 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

    Jenda Guest

  9. #9

    Default Re: SIGZERO

    On Fri, 24 Sep 2004 17:20:44 +0200, Jenda Krynicky <cz> wrote: 
    >
    > 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[/ref]


    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
    Errin Guest

  10. #10

    Default Re: SIGZERO

    > From: Errin Ln <com> 
    >
    > I believe so.[/ref]

    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.
    >[/ref]

    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.).
     

    Yes, as well as,

    perldoc -f wait
    perldoc -f waitpid
     

    http://danconia.org
    Wiggins Guest

  11. #11

    Default Re: SIGZERO

    On Fri, 24 Sep 2004 10:34:50 -0500, Errin Ln <com> wrote: [/ref]

    <<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 confused
    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
    Errin Guest

  12. #12

    Default Re: SIGZERO

    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 Ln <com>
    09/24/2004 11:44 AM
    Please respond to Errin Ln


    To: Jenda Krynicky <cz>
    cc: org
    Subject: Re: SIGZERO


    On Fri, 24 Sep 2004 10:34:50 -0500, Errin Ln <com>
    wrote: 
    wrote: [/ref]

    <<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 confused
    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: org
    For additional commands, e-mail: org
    <http://learn.perl.org/> <http://learn.perl.org/first-response>





    DBSMITH@OhioHealth.com Guest

  13. #13

    Default Re: SIGZERO

    > On Fri, 24 Sep 2004 10:34:50 -0500, Errin Ln
    <com> wrote: [/ref]
    <cz> wrote: [/ref]
    >
    > <<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 confused
    > 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!)
    >[/ref]

    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 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

    Wiggins Guest

  14. #14

    Default Re: SIGZERO

    On Fri, 24 Sep 2004 11:52:19 -0400, com
    <com> wrote: 

    <<SNIP>>

    I'm like you, Derek! I love just reading this stuff. Satisfies some
    inner-geek need I have!

     
    > wrote: [/ref]
    >
    > <<SNIP>>
    >[/ref]

    <<SNIP>>
     

    <<SNIP>>

    Ok, I found this is the Perl Cookbook. Below is a quote:
    " To avoid aculating 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
    Errin Guest

  15. #15

    Default How to check the FILE HANDLE STATUS ???

    hi,
    I want to check the status of File handle before
    reading/writing to file ? How to do this ?

    like following

    open(FH_IN_FILE, ">file.txt");

    # This statement is executed by some other function
    close(FH_IN_FILE);


    print FH_IN_FILE "SOME DATA";

    here before writing to file, i want to check the
    status of FH_IN_FILE..(whether file is opened or
    closed )

    Thanks









    __________________________________
    Do you Yahoo!?
    Yahoo! Mail is new and improved - Check it out!
    http://promotions./new_mail
    Madhu Guest

  16. #16

    Default Re: How to check the FILE HANDLE STATUS ???

    > open(FH_IN_FILE, ">file.txt"); 

    You could do something like the following:
    -----
    #!/usr/local/bin/perl -w
    use strict;

    my %fhs;
    # open the filehandle, store in hash
    open $fhs{one}, '> test1.txt' or die "couldn't write file: $!\n";

    # function takes hashref and name of which filehandle to use
    sub blah {
    my ($fh, $which) = _;
    close $fh->{$which};
    # delete the filehandle when you close it
    delete $fh->{$which};
    }

    blah(\%fhs, 'one');

    # it's closed if it's gone from the hash
    close $fhs{one} if exists $fhs{one};
    -----

    There might be a better way to do whatever you're trying to do,
    though. What's the bigger problem you're trying to solve?

    Dave
    Dave Guest

  17. #17

    Default Re: How to check the FILE HANDLE STATUS ???

    Madhu Reddy wrote: 

    Hello,
     

    if ( defined fileno FH_IN_FILE ) {
    print FH_IN_FILE "SOME DATA";
    }
    else {
    warn "Error: FH_IN_FILE is closed!\n";
    }



    John
    --
    use Perl;
    program
    fulfillment
    John Guest

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139