pht has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks, I humbly ask for opinions regarding the following matter:

perl -e 'open(my $y,"/usr/bin/sleep 5|");die;'

The problem: This program takes five seconds to return to shell prompt despite the die.

I know what's going on -- the perl program waits for the child to terminate, which won't happen until 5 seconds have passed. The prerequisite is that the child does not output anything, otherwise it is likely to die prematurely of borked pipe (cf. /usr/bin/yes -- perl does at least close the file handle before wait()ing).

The big problem corollary: if the child takes forever to exit (eg. /usr/bin/cat /dev/null), so does the perl script.

The question: what are the ways around this? In my reasoning, obviously one must set up a $SIG{__DIE__} handler that forcibly removes the child from existence. I came up only with open2 which returns the pid, that can be then passed to kill 9, $pid. A more esoteric way would be to try to local $SIG{TERM} = 'IGNORE'; kill -15, -$$ or something alike (ie. pop a nuke on all processes in my process group while simultaneously shielding from it).

Replies are listed 'Best First'.
Re: open pipe for input and die
by Corion (Patriarch) on Dec 11, 2008 at 09:26 UTC

    Why not use the fact that a pipe-open returns the PID of the child on success?

    my $child = open my $y, '/usr/bin/sleep 5|' or die "Couldn't spawn: $!/$?"; END { kill 9, $child if $child; };
      Thanks. I didn't realize open will also return the pid, thus i used open2. The rest of the solution is the same though. I have a __DIE__ handler instead of an END block, because the program itself forks later on and I turn the handler off in the child.
Re: open pipe for input and die
by eye (Chaplain) on Dec 13, 2008 at 07:24 UTC
    Other approaches that might be useful in situations like this are:
    • use alarm to schedule a signal before you open the pipe
    • use fork to create a new process; the parent process gets the PID of the child and can kill the child process as needed