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