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

David T. Lewis lewis at mail.msen.com
Fri Jun 6 02:48:52 UTC 2014


The change behaves as described, fixing testHandlerFromAction and introducing
the (now expected) failure into testHandlerRentrancy.

I am not qualified to offer any more useful critique other than to say that
is clear that Nicolas has put some serious thought into this issue and I
hope that others will take a close look at it.

Dave


On Fri, Jun 06, 2014 at 04:13:39AM +0200, Nicolas Cellier wrote:
> 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!
> >
> >
> >

> 



More information about the Squeak-dev mailing list