pjf / ipc-system-simple

Perl module to make running system commands and capturing errors as simple as possible.
http://search.cpan.org/perldoc?IPC::System::Simple
Other
19 stars 20 forks source link

IPC::System::Simple can return "No child processes" (ECHILD) when $SIG{CHLD} is set. #36

Open jkeenan opened 4 years ago

jkeenan commented 4 years ago

(This issue was originally reported on Jun 05 2009 by PJF@cpan.org as https://rt.cpan.org/Ticket/Display.html?id=46684. Transferring it to the current issue tracker.)

Due to the way in which Perl internally handles the reaping of child processes, the presence of a $SIG{CHLD} can prevent IPC::System::Simple from gaining access to return information, which then causes it to throw an exception claiming that it can't start the program, with No child processes as the reason why. Eg:

#!/usr/bin/perl -w
use strict;
use IPC::System::Simple qw(run);
use POSIX;

$SIG{CHLD} = sub { while (waitpid(-1,WNOHANG) > 0) { } };

run("echo hello world");

This looks like it may be hard to fix, but can be worked around by temporarily unsetting the signal handler:

#!/usr/bin/perl -w
use strict;
use IPC::System::Simple qw(run);
use POSIX;

$SIG{CHLD} = sub { while (waitpid(-1,WNOHANG) > 0) { } };

{
    local $SIG{CHLD} = 'DEFAULT';
    run("echo hello world");
}

The only gotcha here is that if your existing signal handler actually did something important, then we're breaking it for the duration of our local block. If the existing signal handler was merely making sure child processes get reaped (which is usually the case), then the code above is harmless.

jkeenan commented 4 years ago

Current behavior (tested on perl-5.14 and 5.30):

$ cat rtc-46684-sig-child.pl 
#!/usr/bin/perl -w
use strict;
use IPC::System::Simple qw(run);
use POSIX;

# https://rt.cpan.org/Ticket/Display.html?id=46684

$SIG{CHLD} = sub { while (waitpid(-1,WNOHANG) > 0) { } };

{
    local $@;
    eval { run("echo hello world"); };
    print "$@\n" if $@;
}

print "Finished\n";
$ perl rtc-46684-sig-child.pl 
hello world
"echo hello world" failed to start: "" at rtc-46684-sig-child.pl line 12.

Finished