in reply to Telling POE to ignore a filehandle for garbage collection purposes?

If you don't need those "sessions hanging around" to do something useful at some later time, you have to figure out what the appropriate state is to send them a _stop event to pull them actively - just guessing...

--shmem

_($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                              /\_¯/(q    /
----------------------------  \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
  • Comment on Re: Telling POE to ignore a filehandle for garbage collection purposes?
  • Download Code

Replies are listed 'Best First'.
Re^2: Telling POE to ignore a filehandle for garbage collection purposes?
by jasonk (Parson) on Mar 18, 2008 at 01:08 UTC

    The problem is that I might need them later, only the garbage collector knows for sure. As an example, if I make the messaging session go away when the last subscription does, then code like this will fail:

    sub handle_something { my ( $kernel, $heap ) = @_[ KERNEL, HEAP ]; $kernel->post( $heap->{ 'messaging_session_id' }, 'unsubscribe_all', ); $kernel->post( $heap->{ 'messaging_session_id' }, 'subscribe' => '/some/message/queue', ); }

    POE's garbage collection includes a bunch of different things in determining if there is any work left to do (pending events, child sessions, handles in use, aliases in use, extra refs, external processes spawned) and basically what I want to do is tell it not to include this one handle in it's consideration, so that the messaging session alone can't keep the process alive, but I don't want to shut the messaging session down completely, because if any of those other things are generating events, then it may still be needed.


    We're not surrounded, we're in a target-rich environment!
Re^2: Telling POE to ignore a filehandle for garbage collection purposes?
by bingos (Vicar) on Mar 18, 2008 at 07:20 UTC

    You don't send a _stop event. POE generates a _stop event to indicate that a session is terminating.

    Not seeing any code, my best guess would be to implement an idle timer on worker socket. I've done this in the past, by storing a time stamp using time() in the heap in a POE::Wheel::ReadWrite's InputEvent handler and FlushedEvent handler. Then have a delayed event that periodically wakes up and checks the time stamp against the current time and takes appropriate action.

    sub _start_wheel { # we've started our wheel and stashed it in the heap. # let's start a delayed event. $kernel->delay( '_wheel_alarm', 60 ); return; } sub _input_handler { # deal with input $heap->{timestamp} = time(); return; } sub _flushed_handler { # Looks like we sent some stuff $heap->{timestamp} = time(); return; } sub _wheel_alarm { my ($kernel,$heap) = @_[KERNEL,HEAP]; # ding dong if ( time() - $heap->{timestamp} > 300 ) { delete $heap->{socket_wheel}; # remove the socket } else { $kernel->delay( '_wheel_alarm', 60 ); } return; }

      After some more digging, I've pretty much come to the conclusion that what I'm trying to do can't be done without mucking around with POE internals....

      Here is the code I finally came up with, though I would prefer there were a way to do it without the monkey-patch. On the other hand though, monkey-patching seems to be part of the core for POE. :)

      # NOTE: This hasn't really had any testing yet... package POE::Resource::Sessions::GCIgnore; use strict; use warnings; our $VERSION = '0.01'; # monkey-patch into POE::Kernel package POE::Kernel; sub _data_ses_collect_garbage { my ( $self, $session ) = @_; # snipping out the ASSERT_DATA/TRACE_REFCOUNT stuff # that was just copied from POE::Resource::Sessions... my $count = $kr_sessions{ $session }->[ SS_REFCOUNT ]; if ( $session->can( 'gc_ignore' ) ) { $count -= $session->gc_ignore; } return if $count > 0; $self->_data_ses_stop( $session ); }

      We're not surrounded, we're in a target-rich environment!