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

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Fri Jun 6 02:13:39 UTC 2014


Though I'm pretty happy with this solution, this late coding definitely
needs more eyes, more tests and advice for rearmHandlerDuring:


2014-06-06 3:57 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.857.mcz
>
> ==================== Summary ====================
>
> Name: Kernel-nice.857
> Author: nice
> Time: 6 June 2014, 3:56:46.41 am
> UUID: 58fb31c3-1c03-4cf6-80d3-1f51f41f6d95
> Ancestors: Kernel-cmm.855
>
> Resolve ExceptionTests>>testHandlerFromAction.
>
> Implementation details:
>
> Do so by intercepting any exception raised by the handle block in the
> context which is invoking this block (see #handleSignal:) and by allways
> propagating this new exception to a previously recorded outerHandler (temp
> at: 3). Since this context is above the handlers (on:do:) on the stack, it
> just has to be marked as a fake handler (<primitive: 199>) to do its
> interceptor/propagator job.
>
> Do not use (temp at: 3) of handler (on:do:) as a marker of enablement
> (true) or temporary disablement (false) during handle block execution,
> since this is completely superseded by above mechanism. We should rather
> rename the (temp at: 3) as outerHandler and set it to nil.
> Since load order counts, and since some #on:do: context down the processes
> stacks are not going to die soon, we have equipped #handleSignal: with a
> workaround, so this change can wait.
>
> Attempt to preserve the possibility for an exception to
> rearmHandlerDuring: aBlock by temporarily resetting the outerHandler temp
> in the interceptorContext (which must be a new inst.var. recorded by the
> Exception).
>
> Alas, the #testHandlerReentrancy is now failing, because it expects an
> inner handler to be triggered by an exception raised from an outer handle
> block, which is forbidden by above implementation. This test is hardly
> compatible with testHandlerFromAction.
>
> I suggest adding an expected failure to document the change of behavior,
> and creating a new test demonstrating how rearmHandlerDuring: could be used.
> If we don't find a real interest in this message now that it cannot pass
> then intercept, we can as well deprecate it.
>
> =============== Diff against Kernel-cmm.855 ===============
>
> Item was changed:
>   ----- Method: ContextPart>>canHandleSignal: (in category
> 'private-exceptions') -----
>   canHandleSignal: exception
>         "Sent to handler (on:do:) contexts only.  If my exception class
> (first arg) handles exception then return true, otherwise forward this
> message to the next handler context.  If none left, return false (see
> nil>>canHandleSignal:)"
>
> +       ^ (((self tempAt: 1) handles: exception))
> -       ^ (((self tempAt: 1) handles: exception) and: [self tempAt: 3])
>                 or: [self nextHandlerContext canHandleSignal: exception].
>   !
>
> Item was changed:
>   ----- Method: ContextPart>>handleSignal: (in category
> 'private-exceptions') -----
>   handleSignal: exception
> +       "Sent to handler (on:do:) and propagator (handleSignal:) contexts
> only.
> +       If I am a handler (on:do:), and 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:).
> +       If I am a propagator (handleSignal:) I just forward the handling
> to the outerHandler (temp at: 3). The propagator is allways above the
> handlers on the stack. If an exception occurs while executing the handle
> block, it will be intercepted by the propagator and redirected to the
> previously recorded outer handler, effectively bypassing all inner and
> current handler."
> -       "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 outerHandler |
> +       <primitive: 199>
> +       (self tempAt: 3) == true ifTrue: [self tempAt: 3 put: nil].
> "preserve compatibility with old handlerContext"
> +       ((self tempAt: 1) handles: exception) ifFalse: [
> +               ^((self tempAt: 3) ifNil: [self nextHandlerContext])
> handleSignal: exception].
> +
> +       exception privHandlerContext: self contextTag from: thisContext
> contextTag.
> +       outerHandler := self nextHandlerContext.  "disable self and all
> inner handlers while executing handle block"
> +       val := (self tempAt: 2) cull: exception.
> -       | val |
> -       (((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"
>   !
>
> Item was added:
> + ----- Method: ContextPart>>rearmHandler:during: (in category
> 'private-exceptions') -----
> + rearmHandler: aHandlerContext during: aBlock
> +       "Sent to interceptor (handleSignal:) contexts only, with a handler
> context (on:do:) parameter.
> +       Makes aHandlerContext re-entrant for the duration of aBlock. Only
> works in a closure-enabled image"
> +
> +       | oldHandler |
> +       oldHandler := self tempAt: 3.
> +       ^ [self tempAt: 3 put: aHandlerContext. aBlock value]
> +               ensure: [self tempAt: 3 put: oldHandler]!
>
> Item was removed:
> - ----- Method: ContextPart>>rearmHandlerDuring: (in category
> 'private-exceptions') -----
> - rearmHandlerDuring: aBlock
> -       "Sent to handler (on:do:) contexts only. Makes me re-entrant for
> the duration of aBlock. Only works in a closure-enabled image"
> -
> -       ^ [self tempAt: 3 put: true. aBlock value]
> -               ensure: [self tempAt: 3 put: false]!
>
> Item was changed:
>   Object subclass: #Exception
> +       instanceVariableNames: 'messageText tag signalContext
> handlerContext outerContext interceptorContext'
> -       instanceVariableNames: 'messageText tag signalContext
> handlerContext outerContext'
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'Kernel-Exceptions-Kernel'!
>
>   !Exception commentStamp: '<historical>' prior: 0!
>   This is the main class used to implement the exception handling system
> (EHS).  It plays two distinct roles:  that of the exception, and that of
> the exception handler.  More specifically, it implements the bulk of the
> protocols laid out in the ANSI specification - those protocol names are
> reflected in the message categories.
>
>   Exception is an abstract class.  Instances should neither be created nor
> trapped.  In most cases, subclasses should inherit from Error or
> Notification rather than directly from Exception.
>
>   In implementing this EHS, The Fourth Estate Inc. incorporated some ideas
> and code from Craig Latta's EHS.  His insights were crucial in allowing us
> to implement BlockContext>>valueUninterruptably (and by extension, #ensure:
> and #ifCurtailed:), and we imported the following methods with little or no
> modification:
>
>   ContextPart>>terminateTo:
>   ContextPart>>terminate
>   MethodContext>>receiver:
>   MethodContext>>answer:
>
>   Thanks, Craig!!!
>
> Item was removed:
> - ----- Method: Exception>>privHandlerContext: (in category 'priv
> handling') -----
> - privHandlerContext: aContextTag
> -
> -       handlerContext := aContextTag!
>
> Item was added:
> + ----- Method: Exception>>privHandlerContext:from: (in category 'priv
> handling') -----
> + privHandlerContext: aContextTag from: anotherContextTag
> +
> +       handlerContext := aContextTag.
> +       interceptorContext := anotherContextTag!
>
> Item was changed:
>   ----- Method: Exception>>rearmHandlerDuring: (in category 'handling')
> -----
>   rearmHandlerDuring: aBlock
>   "Make the current error handler re-entrant while it is running aBlock.
> Only works in a closure-enabled image"
>
> +       ^ interceptorContext rearmHandler: handlerContext during: aBlock!
> -       ^ handlerContext rearmHandlerDuring: aBlock!
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20140606/e59fe369/attachment.htm


More information about the Squeak-dev mailing list