Re: Bug in PoCo::Child when PID wraps round

Ricky Egeland <[email protected]>
Newsgroups gmane.comp.lang.perl.poe
Message-ID <[email protected]>
Hi Erick,

I work with Tony.  I have a new patch now which addresses this issue,  
as well as another leak:  calling $self->wheel($id) will initialize a  
key in $self->{$PKG}{wheels}{$id}, causing a leak if the wheel had  
already finished or if it never existed.

Cheers,
Ricky


=== BEGIN PATCH ===
*** Child.pm	2009-06-02 16:10:53.120660674 +0200
--- Child.pm.patched	2009-05-28 16:38:08.687685140 +0200
***************
*** 265,279 ****

   	# clean up

! 	delete $self->{$PKG}{wheels}{$id};
! 	delete $self->{$PKG}{pids}{$id};

   	# all expiring children should issue a "done" except when
   	# the return code is non-zero which indicates a failure
   	# if the caller asked we quit, fire a "done" regardless
   	# of the child's return code value (we might have hard killed)

! 	my $event = ($self->{$PKG}{wheels}{$id}{quit} || $rc == 0)
   		? "done" : "died"
   		;
   	$self->callback($event, { wheel => $id, rc => $rc });
--- 265,281 ----

   	# clean up

! 	delete $self->{$PKG}{pids}{$self->{$PKG}{wheels}{$id}{ref}->PID};
!         my $wheel = delete $self->{$PKG}{wheels}{$id};
! 	delete $self->{$PKG}{SIGCHLD}{$id};
! 	delete $self->{$PKG}{CLOSED}{$id};

   	# all expiring children should issue a "done" except when
   	# the return code is non-zero which indicates a failure
   	# if the caller asked we quit, fire a "done" regardless
   	# of the child's return code value (we might have hard killed)

! 	my $event = ($wheel->{quit} || $rc == 0)
   		? "done" : "died"
   		;
   	$self->callback($event, { wheel => $id, rc => $rc });
***************
*** 306,311 ****
--- 308,314 ----
   sub wheel {
   	my $self = shift;
   	my $id = shift || $self->{$PKG}{wheels}{current};
+ 	return undef unless exists $self->{$PKG}{wheels}{$id};
   	$self->{$PKG}{wheels}{$id}{ref};
   	}
=== END PATCH ===


On Jun 4, 2009, at 7:30 PM, Erick Calder wrote:

> sorry, I still own it.  I've just been disconnected from the world  
> a long
> time.  it will take me a while to get back to you on this but I will
>
>> From: Tony Wildish <[email protected]>
>> Date: Thu, 7 May 2009 10:58:12 +0200
>> To: <[email protected]>
>> Subject: Re: Bug in PoCo::Child when PID wraps round (fwd)
>>
>> Hi,
>>
>>  just checking one more time: is anyone looking after PoCo::Child,  
>> or is
>> it orphaned?
>>
>>  TIA,
>>  Tony.
>>
>> On Wed, 15 Apr 2009, Tony Wildish wrote:
>>
>>> Hi,
>>>
>>>  I sent this to the [email protected] list some  
>>> time ago
>>> but it looks like that list is dead. Is there someone here managing
>>> PoCo::Child?
>>>
>>>  Cheers,
>>>  Tony.
>>>
>>> ---------- Forwarded message ----------
>>> Date: Tue, 24 Mar 2009 12:56:33 +0100 (CET)
>>> From: Tony Wildish <[email protected]>
>>> To: [email protected]
>>> Subject: Bug in PoCo::Child when PID wraps round
>>>
>>> Hi,
>>>
>>>  we have been using PoCo::Child in a project for a while now and  
>>> have just
>>> uncovered a bug. The internal bookkeeping for the association of  
>>> wheelIDs
>>> and PIDs is wrong, with the result that when the OS PID wraps  
>>> round, the
>>> wrong wheelID will be given to the 'done' event.
>>>
>>>  I'm using PoCo::Child version 1.39, perl 5.8.5, kernel
>>> 2.6.9-78.0.8.EL.cernsmp.
>>>
>>>  You can see the bug by inspection of the code. At line 192 we have:
>>>
>>>         my $id = $wheel->ID;
>>>         $self->debug(qq/run(): "@$cmd", wheel=$id, pid=/ . $wheel- 
>>> >PID);
>>>
>>>         $self->{$PKG}{pids}{$wheel->PID} = $id;
>>>
>>>  so the {pids} are inserted keyed on $wheel->PID. But at line  
>>> 268, the
>>> clean up deletes as follows:
>>>
>>>         delete $self->{$PKG}{wheels}{$id};
>>>         delete $self->{$PKG}{pids}{$id};
>>>
>>>  so it's deleting keyed on wheel->ID, not $wheel->PID.
>>>
>>>  When the PIDs wrap round, the protection in sig_child is broken  
>>> by this:
>>>
>>> sub sig_child {
>>>     my ($kernel, $self, $pid, $rc) = @_[KERNEL, OBJECT, ARG1, ARG2];
>>>
>>>         my $id = $self->{$PKG}{pids}{$pid} || "";
>>>
>>>     # child death signals are issued by the OS and sent to all
>>>     # sessions; we want to handle only our own children
>>>
>>>         return unless $id;
>>>
>>>  Because the {pids} hash had the wrong entry deleted in the  
>>> cleanup, when
>>> the PIDs wrap, an old $id will be found where none should be. So  
>>> sig_child
>>> will not return here, and will cause 'done' to be fired with the old
>>> wheelID, which is plainly wrong.
>>>
>>>  Also, the cleanup around line 268/269 should remove {CLOSED} and
>>> {SIGCHLD} entries for the wheel too. That's less serious because  
>>> it won't
>>> cause a problem until wheel-IDs wrap round, which will take a lot  
>>> longer,
>>> but it's still a leak.
>>>
>>>  Cheers,
>>>  Tony.
>>>
>
>
smime.p7s (application/pkcs7-signature, 2.8 KB) - not displayed
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.