[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
|