Perl fork and kill - kill(0, $pid) always returns 1, and can't kill the child

后端 未结 6 844
孤独总比滥情好
孤独总比滥情好 2021-01-06 07:16

I am running a perl script on a Linux host. I\'m trying to write a script that forks, where the child starts a program that takes forever and the parent times out after 5 s

相关标签:
6条回答
  • 2021-01-06 07:25

    Chances are that you are useing neither strict nor POSIX in your script, so SIGTERM is being interpreted as the bareword "SIGTERM", which isn't behaving in a useful way.

    use strict to make this accidental bareword into an error, then use POSIX to pull in the SIGTERM constant.

    0 讨论(0)
  • 2021-01-06 07:31

    Should be something like this. This isn't following best practices, but it should help you with your problem...

    #!/usr/bin/perl
    
    use warnings;
    use strict;
    use POSIX qw(:sys_wait_h);
    
    my $timeOut = 5;
    $SIG{ALRM} = \&timeout;
    $SIG{CHLD} = 'IGNORE',
    alarm($timeOut);
    
    my $childPid = fork();
    if ($childPid) {
        while(1) {
            print "[$$]: parent...\n"; 
            sleep(2); 
        }
    }else {
        # I am the child - do something that blocks forever
        while(1){
            print "[$$]: child...\n";
            sleep(2);
        }
        exit;
    }
    
    sub timeout {
        print "killing $childPid\n";
        print "###\n" . `ps -ef | grep -v grep | grep perl` . "###\n";
        if ( ! (waitpid($childPid, WNOHANG)) ) {
            print "killing $childPid...\n";
            kill 9, $childPid;
            die "[$$]: exiting\n";
        }
    }
    

    OUTPUT:

    $ forktest.pl
    [24118]: parent...
    [24119]: child...
    [24118]: parent...
    [24119]: child...
    [24118]: parent...
    [24119]: child...
    killing 24119
    ###
    cblack   24118 12548  0 14:12 pts/8    00:00:00 /usr/bin/perl ./forktest.pl
    cblack   24119 24118  0 14:12 pts/8    00:00:00 /usr/bin/perl ./forktest.pl
    ###
    killing 24119...
    [24118]: exiting
    
    0 讨论(0)
  • 2021-01-06 07:37

    I am also seeing this behaviour, that kill 0 returns true even after the process was gone; I suspected you might be missing a call to waitpid (often done in a SIGCHLD handler) which would result in this, but even after adding it, the kill 0 continues to return true.

    I suggest you use non-blocking waitpid instead of kill (and verify that the process actually does die on a SIGTERM signal - some may not, at least immediately). You may also want to try SIGINT after a while if SIGTERM didn't work, and in the last resort SIGKILL.

    0 讨论(0)
  • 2021-01-06 07:37

    I think the problem is with the '0' you are passing as first argument of 'kill'. When I read the docs, they say that '0' will just check to see whether you can send a signal to the process, without sending it. In your case, you want to send the 'KILL' signal to the child process, so do this:

    kill( 'KILL', $childPid );
    
    0 讨论(0)
  • 2021-01-06 07:45

    From perldoc fork:

    If you fork without ever waiting on your children, you will accumulate zombies. On some systems, you can avoid this by setting $SIG{CHLD} to "IGNORE" .

    I was able to get the desired behavior when adding $SIG{CHLD} = 'IGNORE'; to the top of your code.

    [ben@imac ~]$ perl test.pl
    numKilled: 1
    [ben@imac ~]$ 
    

    Alternatively, adding waitpid($childPid, 0); after kill did the trick as well.

    0 讨论(0)
  • 2021-01-06 07:47

    Try killing the process group (use -$pid):

    kill TERM => -$pid;
    

    See perlipc.

    0 讨论(0)
提交回复
热议问题