Re: Suprising POE::Wheel::ReadWrite behaviour
Markus Müller <[email protected]> Sat, 18 Dec 2010 14:12:46 +0100
| Newsgroups | gmane.comp.lang.perl.poe |
|---|---|
| Message-ID | <[email protected]> |
Hi Philip,
I am writing since many years POE projects. One of the
first things I figured out in productive environment is to
test the poe object with defined() and ref(). I had so often
programs running over days or weeks and then just
stopping with a "Can't call method on undefined value",
so I today do defined() and ref() test on any POE object call.
Especially on put!
This looks for example like this:
$heap->{server}->{$wheel_id}->{wheel}->put('xyz')
if (exists
<http://perldoc.perl.org/functions/exists.html>($heap->{server}->{$wheel_id}->{wheel})
&&
defined
<http://perldoc.perl.org/functions/defined.html>($heap->{server}->{$wheel_id}->{wheel})
&&
(ref
<http://perldoc.perl.org/functions/ref.html>($heap->{server}->{$wheel_id}->{wheel})
eq "POE::Wheel::ReadWrite"));
Much regards,
Markus Mueller
> While writing http://search.cpan.org/dist/POEx-HTTP-Server/ I've discovered a
> behaviour of POE::Wheel::ReadWrite that is suprising, to say the least. I
> share it here because I suspect I'm not the only one this has bitten.
>
> I had the following 2 lines
> $heap->{wheel}->flush();
> my $h = $self->{wheel}->get_output_handle;
>
> The symptom was that the second of these two lines would sometimes throw a
> "Can't call method on undefined value" error. Which caused me to bang my
> head on the desk for a while.
>
> But then it dawned on me:
> - ->flush() pushes the data down to the OS layer;
> - POE is then getting a select() in somehow (haven't tracked this down);
> - the select shows the Wheel's write handle is ready;
> - the Wheel's write handler is invoked;
> - which invokes my "flushed" handler;
> - the flushed handler was deleting the wheel;
> - all the happens before ->flush returns;
> - by the time it returns, $self->{wheel} has been deleted.
>
> The answer isn't don't use ->flush(), because ->put() can trigger a driver's
> ->flush(), or call it explicitly if you have autoflush on.
>
> The solution is that all code that uses of ReadWrite need better detection of
> "end of connection."
>
> Now, is this "gotcha" documented anywhere? Should it be? Should there be a
> module that turns ReadWrite's asynchronous behaviour into something easier to
> deal with?
>
> I suspect the answer to the last question is "yes, and you've just volunteered
> to write it, dude."
>
> -Philip
>
>
>