[squeak-dev] The Inbox: Kernel-nice.856.mcz

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Fri Jun 6 00:16:48 UTC 2014


2014-06-06 0:17 GMT+02:00 Nicolas Cellier <
nicolas.cellier.aka.nice at gmail.com>:

>
> 2014-06-05 23:27 GMT+02:00 Nicolas Cellier <
> nicolas.cellier.aka.nice at gmail.com>:
>
> This change resolved the failing test for me, and I did not yet find what
>> else it may break...
>> In this danger zone, more eyes are required, so up to you to refute the
>> method :)
>>
>> I think I have a refutation (theoretically): if an outer handler resumes
> execution in signalContext, then the inner handler context won't be
> re-activated and will miss the next exceptions...
>
> Unfortunately, resuming is the default behavior for any unhandled
> exception (see UndefinedObject>>#handleSignal:).
> So every un-caught exception (even the most harmless Notification) will
> deactivate all the enclosing handlers!
>
> Definitely not a good change, I must find another way...
>
>
I came with a brand new strategy: the goal of the testHandlerFromAction is
that one:
if an exception occurs while evaluating the handler block, we want to
bypass all inner handlers (those inside the protected block).

Since #handleSignal:  is upper on the stack than the inner #on:do: handler,
it could be used to intercept the handling and forward to outer handlers.
So here is an implementation of this strategy:

- mark the #handleSignal: context as a handler (<primitive: 199>) so as to
intercept handling of next exception
- don't let #handleSignal: handle signal, but simply let it pass to the
nextHandlerContext that we pre-recorded in (temp at: 4)
- record the nextHandlerContext in an inst var of #handleSignal: before
executing the handlerBlock [(temp at: 2) cull: exception]

I tested it with this:

1) first add a fourth temp to BlockClosure on:do: for safely inquiring
(temp at: 4)

on: exception do: handlerAction
    "Evaluate the receiver in the scope of an exception handler."

    | handlerActive nextHandler |
    <primitive: 199>  "just a marker, fail and execute the following"
    handlerActive := true.
    nextHandler := nil.
    ^ self value

2) modify ContextPart handleSignal: as described above

handleSignal: exception
    "Sent to handler (on:do: and handleSignal:) contexts only.  If my
exception class (first arg) handles exception then execute my handle block
(second arg), otherwise forward this message to the next handler context.
If none left, execute exception's defaultAction (see nil>>handleSignal:)."

    | val active nextHandler |
    <primitive: 199>
    active := false.
    (((self tempAt: 1) handles: exception) and: [self tempAt: 3]) ifFalse: [
        ^((self tempAt: 4) ifNil: [self nextHandlerContext]) handleSignal:
exception].

    exception privHandlerContext: self contextTag.
    self tempAt: 3 put: false.  "disable self while executing handle block"
    nextHandler := self nextHandlerContext.
    val := [ (self tempAt: 2) cull: exception ]
        ensure: [self tempAt: 3 put: true].
    self return: val.  "return from self if not otherwise directed in
handle block"

If an exception occurs while evaluating the handler block, we are first
finding a #handleSignal: context down the stack,
(temp at: 1) is an Exception instance, not an Exception class, it naturally
does not handles: (Object>>handles:)
Instead, it will just pass the message to the nextHandler (tempAt: 4)...
eventually this continues thru several outer handlers.

With this scheme, I have a my #testHandlerFromAction passing, but a new
failure: #testHandlerReentrancy
Indeed, #testHandlerReentrancy is signalling a Notification from within an
outer handler, how could it possibly search a inner handler?
That's precisely what we tried to avoid !!!

To enable such usage of #rearmHandlerDuring: we would have to annihilate
the nextHandler temp...
But we don't have an access to this #handleSignal: context from within the
exception (it's never the handlerContext, since it does not handles:)
I could possibly add another inst.var. in Exception and fill it with
thisContext from within handleSignal:
Above proposition would have holes (even the not rearmed inner handlers
would be rearmed).
I see no sender of #rearmHandlerDuring: in trunk, and I'm not sure where it
could be usefull...
It seems relatively recent in Squeak (stamp 2010, no previous version).

What do you think?


>> 2014-06-05 23:11 GMT+02:00 <commits at source.squeak.org>:
>>
>> A new version of Kernel was added to project The Inbox:
>>> http://source.squeak.org/inbox/Kernel-nice.856.mcz
>>>
>>> ==================== Summary ====================
>>>
>>> Name: Kernel-nice.856
>>> Author: nice
>>> Time: 5 June 2014, 11:11:07.752 pm
>>> UUID: 44668d33-00c2-4e36-b95b-69d83b0d7544
>>> Ancestors: Kernel-cmm.855
>>>
>>> Attempt to fix ExceptionTests>>#testHandlerFromAction.
>>> When the handler does not handle an Exception, simply mark the handler
>>> context as inactive (self tempAt: 3 put: false).
>>>
>>> =============== Diff against Kernel-cmm.855 ===============
>>>
>>> Item was changed:
>>>   ----- Method: ContextPart>>handleSignal: (in category
>>> 'private-exceptions') -----
>>>   handleSignal: exception
>>>         "Sent to handler (on:do:) contexts only.  If my exception class
>>> (first arg) handles exception then execute my handle block (second arg),
>>> otherwise forward this message to the next handler context.  If none left,
>>> execute exception's defaultAction (see nil>>handleSignal:)."
>>>
>>>         | val |
>>> +       ((((self tempAt: 1) handles: exception) or: [self tempAt: 3 put:
>>> false])
>>> +                and: [self tempAt: 3]) ifFalse: [
>>> -       (((self tempAt: 1) handles: exception) and: [self tempAt: 3])
>>> ifFalse: [
>>>                 ^ self nextHandlerContext handleSignal: exception].
>>>
>>>         exception privHandlerContext: self contextTag.
>>>         self tempAt: 3 put: false.  "disable self while executing handle
>>> block"
>>>         val := [(self tempAt: 2) cull: exception ]
>>>                 ensure: [self tempAt: 3 put: true].
>>>         self return: val.  "return from self if not otherwise directed
>>> in handle block"
>>>   !
>>>
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20140606/c540642f/attachment.htm


More information about the Squeak-dev mailing list