Hi Denis,

Thanks very much for the clarification in your previous email (which I
haven't quoted here), I did indeed misunderstand the point you were
making.


On Thu, 19 Dec 2019 at 19:40, Denis Kudriashov <[email protected]> wrote:
>
> The solution to problem is to resignal UnhandledError instead of simple 
> signalling. Resignal uses original signalContext as a starting point for 
> handlers lookup:
>
> UnhandledError>>signalForException: anError
>
> ^anError resignalAs: (self new
>
> exception: anError;
>
> yourself)
>
>
> I played with some of debugger issues and this code really fixes them.
> For example try debug following script in playground:
>
> [
>  self methodWithError
> ] on: Error do: [ :e | e logCr. e pass ]
>
> With error method:
>
>
> Object>>methodWithError
>
> 1/0
>
> Step into #methodWithError and then stepThrough "1/0".
> In current image it will hands for a while and then it will open another 
> debugger with single error item. The current debugger process will be broken.
> Now try to apply proposed change for UnhandledError>>signalForException: and 
> repeat experiment. StepThrough "1/0" will move debugger to ZeroDivide signal 
> showing correct stack.

Confirmed.


> Notice that debugging separate "self methodWithError" without outer handler 
> works correctly in both cases. But you should be in clean stack without 
> hidden outer handlers. And in Playground or when you use debugIt it is clean.
> But you can try in "bad" environment. Execute in browser editor "self halt. 
> self methodWithError". And in debugger just Step Through #methodWithError. It 
> will hangs. Proposed change fixes that.
>
> I will prepare PR with tests. But it would be nice to find other broken 
> places which will be fixed

I thought I'd take a look at VisualWorks (8.3) to see what it does: it
has the same behaviour as with your fix above.

This opens some other interesting possibilities.  Changing some names
and reinterpreting your original example:

[
result := [ MyResumableError signal ] on: UnhandledError do: [ :e |
self doUltimateFallback ]
] on: MyResumableError do: [ :e | e resume: 42 ].

The MyResumableError handler may be way down the call stack.

While the code is more than a little contrived, it does demonstrate
the possibility of allowing callers to handle exceptions, but then
have a fallback if everything else fails.

Great detective work!

Thanks,
Alistair

Reply via email to