perl alarm with subprocess

前端 未结 1 1852
一个人的身影
一个人的身影 2021-01-12 17:27

I have a perl script that runs a series of batch scripts for regression testing. I want to implement a timeout on the batch scripts. I currently have the following code.

1条回答
  •  一整个雨季
    2021-01-12 18:02

    It's hard to tell when alarm will work, when a system call will and won't get interrupted by a SIGALRM, how the same code might behave differently on different operating systems, etc.

    If your job times out, you want to kill the subprocess you have started. This is a good use case for the poor man's alarm:

    my $pid = open CMD, "$cmd 2>&1 |";
    my $time = $MAX_TIMEOUT;
    
    my $poor_mans_alarm = "sleep 1,kill(0,$pid)||exit for 1..$time;kill -9,$pid";
    if (fork() == 0) {
        exec($^X, "-e", $poor_mans_alarm);
        die "Poor man's alarm failed to start";  # shouldn't get here
    }
    # on Windows, instead of  fork+exec, you can say
    #    system 1, qq[$^X -e "$poor_mans_alarm"]
    
    
    ...
    

    The poor man's alarm runs in a separate process. Every second, it checks whether the process with identifier $pid is still alive. If the process isn't alive, the alarm process exits. If the process is still alive after $time seconds, it sends a kill signal to the process (I used 9 to make it untrappable and -9 to take out the whole subprocess tree, your needs may vary).

    (The exec actually may not be necessary. I use it because I also use this idiom to monitor processes that might outlive the Perl script that launched them. Since that wouldn't be the case with this problem, you could skip the exec call and say

    if (fork() == 0) {
        for (1..$time) { sleep 1; kill(0,$pid) || exit }
        kill -9, $pid;
        exit;
    }
    

    instead.)

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