[PATCH] AnyEvent::Handle

Maxime Soulé btik-cpan at scoubidou.com
Thu Jul 5 16:28:44 CEST 2012


OK I understood your point of view.

We started from "storable" read type disagreement to reach the general 
problem of fatal exceptions in AnyEvent.

So I have a few related questions, just to be sure I will do the right 
thing at the right moment:

Le 04.07.2012 21:38, Marc Lehmann wrote:
> On Wed, Jul 04, 2012 at 10:40:25AM +0200, Maxime Soulé<btik-cpan at scoubidou.com>  wrote:
>> To get round that, I need to put an eval {} in my callback with a
>> "catch" block that call AnyEvent::postpone to "die" later, just in
>> case...
>
> That is correct.

OK. So related to what you say below, I must not use "die" in the 
AnyEvent::postpone callback, right? Or is it OK in this case?

>
>> All of this is not needed for chunk, line, regex, netstring,
>> packstring, json and tls_detect (and so tls_autostart).
>
> Why, because your code is beyond perfect? Can you *prove* that it isn't
> needed?
>
> Since I doubt you can, you still need to catch exceptions if you want to
> handle them in some specific way.
>
>> It is just a pity to not have the same simple behaviour for storable
>> than for others in the same module, and so perhaps at the same time,
>> define one for all read_type writers.
>
> The behaviour is the same, and simple, as I have explained. If you think
> the behaviour is not the same, then can you explain what the difference
> is?

"storable" is the only type reader that enclose the callback in an eval 
{}. Even if that does not change what you say later about the recv call 
context.

>
>> Of course I can define a new storable read type, but that is not the
>> goal, I think it is better to talk about existing code :)
>
> There is no known issue with the current code.
>
>>>> Or not
>>>
>>> Since ou disagree, can you describe the mechanism that takes away the
>>> chance of it being reported?
>>
>> The main $cv->recv is included in an eval {}, so I can catch the
>> error, log it before aborting the program
>
> No, you cnanot. Not in theory, because AnyEvent doesn't allow that
> behaviour, and not in practise, because recv will not always call your
> callback directly, or without an eval on it's own (in fact, most event
> loops catch exceptions).

Yes sorry, I didn't say previously that I rely on the perl event loop 
that does not seem to catch exceptions. So it seems to me that my global 
eval {} works in this case.

When I use AnyEvent over EV, I use $EV::DIED to signal (send) the global 
condvar with the error, and so leave the application. Is this behaviour 
correct?

It allows me to consider untrapped exceptions as fatal ones and then to 
quit in these cases.

>
> If you rely on an eval around recv, that's a bug in your code you would
> need to fix first. If you fix that bug, most likely all your problems will
> instantly evaporate with it :)
>
>> case, that these untrapped exceptions are fatal ones. This mechanism
>> is application dependant, this is one example I use.
>
> No, it's just a bug that luckily hasn't bitten you yet.

OK, I understand.

>
>>> No, *any* program behaviour can always be caused by a bug as wlel, as
>>> would be the case in this case.
>>
>> Of course, but it could be cool to be able to easily detect "perl
>> critical exceptions" without having to obstruct my callback with
>> eval/catch block...
>
> Try AE_DEBUG_WRAP then, which does it for you, or you can providde a
> simpler wrapper function.
>
> Besides, from your explanation of "critical exceptions", it's not clear to
> me how one would implement that, since that seems to be a very personal
> definitino of what to catch and what to do - you need to implement that
> yourself, for example using a wrapper (mysub { ... });
>
>>> AnyEvent cannot know which errors are and are not fatal to your
>>> application. It could wrap each watcher callback into an eval to get some
>>> defined behaviour (and you can do that using the wrap functionality), but
>>> it does not enforce this.
>>
>> Please, excuse me to insist :), but in the storable case, it does
>> enforce this.
>
> Insistence on something doesn't make it true. AnyEvent doesn't enforce it,
> even in the storable case. That's a fact that no amount of insistence can
> change.

:)

>
>>> It is simply a bug, no matter what AnyEvent::Handle does.
>>
>> I agree with you, a bug is a bug. It could just be cool that
>> AnyEvent::Handle only catches exceptions in its own code, but not in
>> the user code (except when the user wants it by using AE_DEBUG_WRAP)
>> and let the application handle all other exceptions, because only the
>> application knows exactly what to do in such cases.
>
> Well, it's impossible to implement, which instantly rules that out.
>
> But even if it were possible to implement, it couldn't be done by wrapping
> recv inside an eval, since you have no guarantee over the order of things,
> and who calls recv when, or when when the callback is called.
>
> You'd receive exceptions from code you are not designed to recv eception
> from, and you would not see exceptions form your own code sometimes.
>
> So putting an eval around your recv would be a bug, it wouldn't achieve
> what you want.
>
> And encouraging bugs doesn't look so cool to me :)
>
>> Please note that all that discussion comes from the position of an
>> eval {} in a code line ;-)
>
> Which resulted in finding all kinds of bugs in your code, so that's gerat,
> isn't it? Without it, you'd never find out about the bugs until they are
> biting you.

It is... And I am very lucky guy since my eval {} trick did not fool me 
for 4 years :)

But never say never.

Thank you for your work and for your time!

Best regards,

Max.



More information about the anyevent mailing list