Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Killing process group run with IPC::Open3

by pm_sanchay (Initiate)
on Feb 02, 2012 at 23:11 UTC ( #951554=perlquestion: print w/ replies, xml ) Need Help??
pm_sanchay has asked for the wisdom of the Perl Monks concerning the following question:

use strict; use warnings "all"; use IPC::Open3; use POSIX; my $timeout = shift @ARGV; my ($cpid); eval{ local $SIG{ALRM} = sub {die "alarm\n"}; alarm $timeout; #setsid(); #setpgrp(0,0); $cpid = open3("<&STDIN", ">&STDOUT", ">&STDERR", @ARGV) or die $! +; waitpid($cpid, 0); alarm 0; }; if($@){ die if $@ ne "alarm\n"; print "timed out\n"; my $num = kill 15, $cpid; print "sent kill to $num\n"; waitpid($cpid, 0); }
Here's output:

$ perl test.pl 2 perl -e 'system("sleep 3; echo My work is done")'
timed out
sent kill to 1
$ My work is done

As you see child child process didn't get killed. If run with kill -15 and setsid uncommened:

> perl test.pl 2 perl -e 'system("sleep 3; echo My work is done")'
timed out
sent kill to 0
My work is done

Please teach me how to kill entire process group spawned by IPC::Open3.  Final goal is to be able to timeout a process, which spawns child (child accepts input from STDIN).

Thanks

Comment on Killing process group run with IPC::Open3
Download Code
Re: Killing process group run with IPC::Open3
by ikegami (Pope) on Feb 03, 2012 at 00:06 UTC

    I'm guessing the process to which you send a "negative signal" must be the head of a process group. Testing corroborates.

    $ perl test.pl 2 perl -e'system("sleep 4; echo My work is done")' timed out sent kill to 0 My work is done $?=0 $ perl test.pl 2 perl -MPOSIX -e'setpgrp(0,0); system("sleep 4; echo M +y work is done")' timed out sent kill to 1 $?=15

    You could solve your problem by using the following:

    eval{ local $SIG{ALRM} = sub {die "alarm\n"}; alarm $timeout; $cpid = open3("<&STDIN", ">&STDOUT", ">&STDERR", '-'); if (!$cpid) { # Child setpgrp(0,0); exec(@ARGV) or die "exec: $!"; } waitpid($cpid, 0); alarm 0; };
    $ perl fixed.pl 2 perl -e'system("sleep 4; echo My work is done")' timed out sent kill to 1 $?=15

    This code works with older version of Perl (e.g. Perl 5.10), but I'm getting an "illegal seek" error with newer version of Perl. I'll look into it. Especially since I think it might be in the code I wrote for open3 X_X.

    PS — open3(...) or die $!; is wrong. open3 dies on error rather than returning false.

      
      Hi ikegami,
      
      That's a good point and infact I tried exec first (that's why use of setpgrp).  But problem is I also need to capture <stdin> in my app. Here is example:
      
      > cat app.pl
      print "continue? "; $yesno=<STDIN>; print "--$yesno";
      
      > perl fixed.pl 5 perl -e 'system("perl app.pl")'
      continue? y
      alarmed out
      sent kill signal to 1
      ^C
      
      > perl test.pl 5 perl -e 'system("perl app.pl")'
      continue? y
      --y
      Child exit status: 0 signal: 0
      
      Is there any way to map <STDIN> in fixed.pl ?
      
      

        Capture an input? Your terminology makes no sense to me. What do you mean by "capture <stdin>"?

        Whatever it is you want to do, if you know how to do it with open3, keep doing it that way. There's nothing special about "fixed.pl" on that side of things.

        PS — Please don't use <pre>. At all. Place code, computer text, inputs, outputs, etc in <code></code> or <c></c> tags. And use <p> at the start of paragraphs.

        So I ran a few tests. It seems that the child can't read from the parent's STDIN. I presume this is the problem to which you are referring.

        man 2 setpgrp explains

        At any time, one (and only one) of the process groups in the session can be the foreground process group for the terminal; the remaining process groups are in the background.

        I don't know what a session is, but adding setsid() appears to solve the problem.

Re: Killing process group run with IPC::Open3
by zentara (Archbishop) on Feb 03, 2012 at 10:21 UTC

      Proc::Killfam works with IPC::Open3 to achieve what I want, Thanks ! But I'm not sure how my manager will react to adding a non-core module dependency.

        But I'm not sure how my manager will react to adding a non-core module dependency.

        You could copy the essential code from the Killfam.pm right into your code, avoiding using a module. The code is very simple, use "perldoc -m Proc::Killfam" to see the module's simple code.


        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku ................... flash japh

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://951554]
Approved by ikegami
Front-paged by chrestomanci
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (6)
As of 2014-12-21 10:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (104 votes), past polls