Re: _stop state isn't called on child when parent gets Ctrl-C (EasyDBI session still active)
*This definitely has to do with the open EasyDBI session
I tested this by shutting down the EasyDBI session from inside the child
manually before a Ctrl-C and indeed the shutdown works fine with no orphaned
processes.
(Called this before Control-C)
sub my_test_handler_before_ctrl_c{
POE::Kernel->post( 'EasyDBI', 'shutdown' => 'NOW' );
}
...program running...
(CONTROL-C HERE)
(All 3 children reaped)
MAIN STOP CALLED
!!! Child process PID:18268 reaped:
!!! Child process PID:18267 reaped:
!!! Child process PID:18266 reaped:
So the real question is, how do I handle this correctly..Do I handle
this in the parent by looking for open sessions or do I handle this on the
child side by adding signal handlers?
Any and all suggestions welcome. Thanks in advance for any advice
On Fri, May 8, 2009 at 5:48 PM, Josh803316 wrote:
> Hello once again POE world,
>
> *I have a problem with a child daemon process not being killed when I hit
> Ctrl-C for the parent. All other children are reaped but one remains. This
> child happens to be the one using EasyDBI.
> *I have noticed that when I hit Ctrl-C..I don't see the _stop event
> called for any of the spawned children. This _stop event is what calls
> $kernel->post(
> 'EasyDBI', 'shutdown' => 'NOW' );
> *I'm assuming that the reason the child stays around is because the EasyDBI
> session is still alive.
>
> 1)Parent uses wheel::run to spawn workers (database worker only one that
> stays alive)
>
> 2)Database worker child spawns EasyDbi session as well as other sessions
>
> 3)Everything runs normally then I hit Ctrl-C which kills the parent
> process, then shows all the other children reaped but hangs on the final one
> !!! Child process PID:17843 reaped:
> !!! Child process PID:17842 reaped:
> hangs here
>
> 4)A second Ctrl-C ends the program (with child process still running)
> # ps aux | grep perl
> root 17841 2.7 1.0 153992 21276 pts/5S17:18 0:00
> /usr/bin/perl ./WorkerDbd (This process should be gone)
>
>
> (PARENT Daemon)
> ##
> foreach my $key (keys %$workers ){
> foreach my $worker ( @{$workers->{$key}} ){
> print "The worker is $worker\n";
> POE::Session->create(
> inline_states => {
> _start => \&on_start,
> _child => \&_child,
> got_child_stdout => \&on_child_stdout,
> got_child_stderr => \&on_child_stderr,
> got_child_close => \&on_child_close,
> got_child_signal => \&on_child_signal,
> _stop=> \&_stop
> },
> args => [$worker]
> );
> }
> }
>
> sub on_start {
> my ( $kernel, $session, $heap, $worker ) = @_[ KERNEL, SESSION, HEAP,
> ARG0 ];
> my $child = POE::Wheel::Run->new(
> Program => [ "./$worker" ],
> StdoutEvent => "got_child_stdout",
> StderrEvent => "got_child_stderr",
> CloseEvent => "got_child_close",
> );
>
> $_[KERNEL]->sig_child($child->PID, "got_child_signal");
>
> # Wheel events include the wheel's ID.
> $_[HEAP]{children_by_wid}{$child->ID} = $child;
>
> # Signal events include the process ID.
> $_[HEAP]{children_by_pid}{$child->PID} = $child;
>
> print(
> "Child pid ", $child->PID,
> " started as wheel ", $child->ID, ".\n"
> );
> }
>
> ##
> (Database Worker CHILD Daemon)
> POE::Kernel->stop();
> POE::Component::IKC::Responder->spawn();
>
> POE::Component::EasyDBI->spawn( # or new(), witch returns an obj
> alias => 'EasyDBI',
> dsn =>
> 'DBI:mysql:database=foobaz;host=localhost;port=3306',
> username=> 'username',
> password=> 'password',
> options => {
> AutoCommit => 0,
> },
> );
>
> App::Database->__spawn();
>
> POE::Kernel->run();
>
> (Package)
> App::Database
> sub __spawn {
> my $class = shift;
>
> my $addr = $class->IP || '127.0.0.1';
> my $port = $class->PORT || 5667;
> my $trace = $class->TRACE || 0;
> my $debug = $class->DEBUG || 0;
> my $client = $class->ALIAS || "Client$$";
> my $workername = $client . 'Worker';
>
> ## spawn the ikc client with unique workername
> my $server = POE::Component::IKC::Client->spawn(
> ip => $addr,
> port => $port,
> name => $workername,
>
> on_connect => sub {
> $_[HEAP]->{channel} = $poe_kernel->get_active_session()->ID;
> print STDERR Dumper($_[HEAP]);
> POE::Session->create(
>
> package_states =>
> ## extract all subroutines that don't start with "__"
> ## and allocate them as states:
> [
> (__PACKAGE__) => [ do
_stop state isn't called on child when parent gets Ctrl-C (EasyDBI session still active)
Hello once again POE world,
*I have a problem with a child daemon process not being killed when I hit
Ctrl-C for the parent. All other children are reaped but one remains. This
child happens to be the one using EasyDBI.
*I have noticed that when I hit Ctrl-C..I don't see the _stop event
called for any of the spawned children. This _stop event is what
calls $kernel->post(
'EasyDBI', 'shutdown' => 'NOW' );
*I'm assuming that the reason the child stays around is because the EasyDBI
session is still alive.
1)Parent uses wheel::run to spawn workers (database worker only one that
stays alive)
2)Database worker child spawns EasyDbi session as well as other sessions
3)Everything runs normally then I hit Ctrl-C which kills the parent process,
then shows all the other children reaped but hangs on the final one
!!! Child process PID:17843 reaped:
!!! Child process PID:17842 reaped:
hangs here
4)A second Ctrl-C ends the program (with child process still running)
# ps aux | grep perl
root 17841 2.7 1.0 153992 21276 pts/5S17:18 0:00
/usr/bin/perl ./WorkerDbd (This process should be gone)
(PARENT Daemon)
##
foreach my $key (keys %$workers ){
foreach my $worker ( @{$workers->{$key}} ){
print "The worker is $worker\n";
POE::Session->create(
inline_states => {
_start => \&on_start,
_child => \&_child,
got_child_stdout => \&on_child_stdout,
got_child_stderr => \&on_child_stderr,
got_child_close => \&on_child_close,
got_child_signal => \&on_child_signal,
_stop=> \&_stop
},
args => [$worker]
);
}
}
sub on_start {
my ( $kernel, $session, $heap, $worker ) = @_[ KERNEL, SESSION, HEAP,
ARG0 ];
my $child = POE::Wheel::Run->new(
Program => [ "./$worker" ],
StdoutEvent => "got_child_stdout",
StderrEvent => "got_child_stderr",
CloseEvent => "got_child_close",
);
$_[KERNEL]->sig_child($child->PID, "got_child_signal");
# Wheel events include the wheel's ID.
$_[HEAP]{children_by_wid}{$child->ID} = $child;
# Signal events include the process ID.
$_[HEAP]{children_by_pid}{$child->PID} = $child;
print(
"Child pid ", $child->PID,
" started as wheel ", $child->ID, ".\n"
);
}
##
(Database Worker CHILD Daemon)
POE::Kernel->stop();
POE::Component::IKC::Responder->spawn();
POE::Component::EasyDBI->spawn( # or new(), witch returns an obj
alias => 'EasyDBI',
dsn => 'DBI:mysql:database=foobaz;host=localhost;port=3306',
username=> 'username',
password=> 'password',
options => {
AutoCommit => 0,
},
);
App::Database->__spawn();
POE::Kernel->run();
(Package)
App::Database
sub __spawn {
my $class = shift;
my $addr = $class->IP || '127.0.0.1';
my $port = $class->PORT || 5667;
my $trace = $class->TRACE || 0;
my $debug = $class->DEBUG || 0;
my $client = $class->ALIAS || "Client$$";
my $workername = $client . 'Worker';
## spawn the ikc client with unique workername
my $server = POE::Component::IKC::Client->spawn(
ip => $addr,
port => $port,
name => $workername,
on_connect => sub {
$_[HEAP]->{channel} = $poe_kernel->get_active_session()->ID;
print STDERR Dumper($_[HEAP]);
POE::Session->create(
package_states =>
## extract all subroutines that don't start with "__"
## and allocate them as states:
[
(__PACKAGE__) => [ do {
no strict 'refs';
grep { !/^__/ and defined &$_ } keys %{
__PACKAGE__ . "::" };
} ],
($class) => [ $class->SUBSCRIBE_METHODS ]
],
## pass args into _start:
args => [$class,@_],
options => { trace => $trace, debug => $debug },
);
}
);
return $server;
}
sub _start {
my ( $kernel, $session, $heap, $class, $arg1 ) = @_[ KERNEL, SESSION,
HEAP, ARG0, ARG1 ];
my $states;
my $alias = $class->ALIAS;
# name this session
if($class){
$kernel->alias_set($alias);
$kernel->post( 'IKC', 'publish', $alias, [$class->SUBSCRIBE_METHODS]
);
$class->__startup($kernel,$session,$heap);
}
}
sub _stop {
my ( $kernel, $session, $heap, $arg ) = @_[ KERNEL, SESSION, HEAP, ARG0
];
print STDERR "STOP WAS CALLED FOR THE WORKER TEMPLATE $session->ID\n";
$kernel->post( 'EasyDBI', 'shutdown' => 'NOW' );
$
