Thanks, Olivier,
Finally I can get the script working except one problem left: How can I reap
child process?

Below is my code. If I input CTRL-C when the script asking for a username or
password, the script dose not exit even if I use $SIG{CHLD}='IGNORE'. By 'ps
-ef', I can see that the get_name.pl is in the state of  "zombie" and
waiting for the parent process to reap.



$|++;
use POE qw( Wheel::ReadLine Wheel::Run  );
*POE::Kernel::USE_SIGCHLD = sub (){1};
$SIG{CHLD} = 'ignore';
POE::Session->create(
    inline_states => {
        _start           => \&on_start,
        got_child_stdout => \&on_child_stdout,
        got_child_stderr => \&on_child_stderr,
        got_child_close  => \&on_child_close,
        got_child_signal => \&on_child_signal,
        got_user_input   => \&read_from,
    }
);

POE::Kernel->run();
exit 0;

sub on_start {
    $_[HEAP]->{stdin} =
      POE::Wheel::ReadLine->new(InputEvent => 'got_user_input');

    my $consol = $_[HEAP]->{stdin};
    $_[HEAP]->{job} = POE::Wheel::Run->new(
        Program      => ["perl get_name.pl"],
        StdoutEvent  => "got_child_stdout",
        StderrEvent  => "got_child_stderr",
        CloseEvent   => "got_child_close",
        StdioFilter  => POE::Filter::Line->new(),
        StderrFilter => POE::Filter::Line->new(),
        Conduit      => 'pty',
    );
    my $child = $_[HEAP]->{job};
    my $pid   = $child->PID;

    $_[KERNEL]->sig_child("$pid, got_child_signal");
    $_[HEAP]->{stdin}->put("Child pid $pid,  started as wheel , $pid");
}

sub on_child_stdout {
    my ($stdout_line) = @_[ARG0];
    my $child         = $_[HEAP]{job};
    my $pid           = $child->PID;
    $_[HEAP]->{stdin}->put("pid $pid, STDOUT: $stdout_line");
    $_[HEAP]->{stdin}->get("");
}

sub on_child_close {
    my $wheel_id = $_[ARG0];
    my $child    = delete $_[HEAP]{job};

    unless (defined $child) {
        $_[HEAP]->{stdin}->put("wid $wheel_id closed all pipes.\n");
        return;
    }
}

sub on_child_signal {
    $_[HEAP]->{stdin}->put("pid $_[ARG1] exited with status $_[ARG2].\n");
    my $child = delete $_[HEAP]{job};

    # May have been reaped by on_child_close() .
    return unless defined $child;
    delete $_[HEAP]{children_by_wid}{$child->ID};
}

sub read_from {
    my ($input, $exception) = @_[ARG0, ARG1];
    my $console = $_[HEAP]->{stdin};
    my $job     = $_[HEAP]->{job};
    unless (defined $input) {
        $console->put("Exception got, existing....");
        $job && $job->kill();
        return;
    }
    $_[HEAP]->{stdin}->put("got: $input");
    $_[HEAP]->{job}->put($input);
}

2009/9/26 Olivier Mengué <olivier.men...@gmail.com>

> 2009/9/25 woosley. xu. <redic...@gmail.com>
>
> > besides, if you write the interactive code like this:
> >
> >    my $user = <STDIN>;
> >    chomp $user;
> >    $_[HEAP]->{job}->put("$user");
> >    my $pass = <STDIN>;
> >    chomp $pass;
> >    $_[HEAP]->{job}->put("$pass");
> >
> > It won't pop up all the message from the child process until you finished
> > all your input. Maybe this is not the right way to do it, I am wondering
> > which is the way.
> >
> > You should do user input in the POE way too: by watching events coming
> from
> STDIN.
> Maybe POE::Wheel::ReadLine is what you need.
>
> Olivier.
>



-- 
Woosley.Xu
Tju->PMO->Rdps

Reply via email to