IPC::Open3 and determining if child is waiting for input

做~自己de王妃 提交于 2020-01-01 16:04:39

问题


sub run_command
{
    my $COMMAND         = shift;
    my @OUTPUT;
    my %CMD             = {};

    $CMD{pid}           = open3(my $CH_IN, my $CH_OUT, my $CH_ERR, $COMMAND);
    $CMD{_STDIN}        = $CH_IN;
    $CMD{_STDOUT}       = $CH_OUT;
    $CMD{_STDERR}       = $CH_ERR;

    my $line            = readline $CMD{_STDOUT};
    print $line;

#    open my $CMDPROC, q{-|}, $COMMAND   or return;
#    foreach (<$CMDPROC>)
#    {
#        push @OUTPUT, "$ARG";
#    }
    close $CMDPROC                      or return;

    return @OUTPUT
}

The above code is part of a script I am writing which needs to run another script (called child). The child may or may not prompt for input, depending on the presence of a cookie file in /var/tmp (both scripts written on CentOS5 / perl 5.8.8)

I need to determine if and when the child is waiting for input, so that the parent can pass input from STDIN of parent. I also need to use open3 to open the child process, as I need for parent to pass the brutal (Severity 1) check of Perl::Critic.

I included the comments, because when the cookie file is already set, I can at least get parent to call child properly since child doesn't wait for input in that case.

I've checked around trying to find examples of how to determine if the child is waiting for input. The one example I found used strace (http://www.perlmonks.org/?node_id=964971) and I feel as though that might be too complex for what I am trying to do.

Any links to guide me will be greatly appreciated.


回答1:


You can check if there's space in the pipe (using select). You can even check how much space is available in the pipe. However, I've never heard of the ability to check if a thread is blocked waiting to read from the pipe. I think you should explore other avenues.


It seems to me that a program that only reads from STDIN when certain conditions unrelated to arguments are met would provide a prompt indicating it's waiting for input. If that's the case, one could use Expect to launch and control the child program.

But the simplest solution would be to write the data to STDIN unconditionally. Implementing this using IPC::Open3 is very complicated[1], so I recommend switching to IPC::Run3 (simpler) or IPC::Run (more flexible).

# Capture's child's STDERR
run3 [ $prog, @args ], \$text_for_stdin, \my $text_from_stdout, \my $text_from_stderr;

or

# Inherits parent's STDERR
run3 [ $prog, @args ], \$text_for_stdin, \my $text_from_stdout;

  1. When you both write to the child's STDIN and read from the child's STDOUT, you need to use select (or something else) to avoid deadlocks. IPC::Open3 is very low level and doesn't do this for you, whereas handling this are IPC::Run3 and IPC::Run raison d'être.


来源:https://stackoverflow.com/questions/41454627/ipcopen3-and-determining-if-child-is-waiting-for-input

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!