<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">2014-06-06 12:43 GMT+02:00 Nicolas Cellier <span dir="ltr"><<a href="mailto:nicolas.cellier.aka.nice@gmail.com" target="_blank">nicolas.cellier.aka.nice@gmail.com</a>></span>:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2014-06-06 4:48 GMT+02:00 David T. Lewis <span dir="ltr"><<a href="mailto:lewis@mail.msen.com" target="_blank">lewis@mail.msen.com</a>></span>:<div class="">
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">The change behaves as described, fixing testHandlerFromAction and introducing<br>
the (now expected) failure into testHandlerRentrancy.<br>
<br>
I am not qualified to offer any more useful critique other than to say that<br>
is clear that Nicolas has put some serious thought into this issue and I<br>
hope that others will take a close look at it.<br>
<br>
Dave<br>
<div><div><br></div></div></blockquote></div><div><div><br>Thanks David,<br></div>Added wisdom: googling about usage of #rearmHandlerDuring: it seems required by Island mechanism in Tweak see<br><a href="https://code.google.com/p/pharo/issues/detail?id=2519" target="_blank">https://code.google.com/p/pharo/issues/detail?id=2519</a><br>
<br></div><div>Maybe there is another implementation possible in Tweak, but that's definitely the main usage of #rearmHandlerDuring:<br><br></div><div>I also see this hack in VMMaker:<br><a href="http://forum.world.st/VM-Maker-VMMaker-oscog-eem-180-mcz-td4637135.html" target="_blank">http://forum.world.st/VM-Maker-VMMaker-oscog-eem-180-mcz-td4637135.html</a><br>
</div><div>found after this thread:<br><a href="http://web.archiveorange.com/archive/v/kLJIkmCV2lbVUoHLbp3R" target="_blank">http://web.archiveorange.com/archive/v/kLJIkmCV2lbVUoHLbp3R</a><br></div><div><br></div><div>I'll try and give a try to above Eliot's snippets<br>
<br><br></div></div></div></div></blockquote><div><br>And good news, the new implementation of rearmHandlerDuring: is still work on Eliot's snippets (#caught is correctly transcripted 5 times).<br></div><div>Though the count of second snippet is still 1.<br>
<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><div><div class="h5"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div><div>
<br>
On Fri, Jun 06, 2014 at 04:13:39AM +0200, Nicolas Cellier wrote:<br>
> Though I'm pretty happy with this solution, this late coding definitely<br>
> needs more eyes, more tests and advice for rearmHandlerDuring:<br>
><br>
><br>
> 2014-06-06 3:57 GMT+02:00 <<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>>:<br>
><br>
> > A new version of Kernel was added to project The Inbox:<br>
> > <a href="http://source.squeak.org/inbox/Kernel-nice.857.mcz" target="_blank">http://source.squeak.org/inbox/Kernel-nice.857.mcz</a><br>
> ><br>
> > ==================== Summary ====================<br>
> ><br>
> > Name: Kernel-nice.857<br>
> > Author: nice<br>
> > Time: 6 June 2014, 3:56:46.41 am<br>
> > UUID: 58fb31c3-1c03-4cf6-80d3-1f51f41f6d95<br>
> > Ancestors: Kernel-cmm.855<br>
> ><br>
> > Resolve ExceptionTests>>testHandlerFromAction.<br>
> ><br>
> > Implementation details:<br>
> ><br>
> > Do so by intercepting any exception raised by the handle block in the<br>
> > context which is invoking this block (see #handleSignal:) and by allways<br>
> > propagating this new exception to a previously recorded outerHandler (temp<br>
> > at: 3). Since this context is above the handlers (on:do:) on the stack, it<br>
> > just has to be marked as a fake handler (<primitive: 199>) to do its<br>
> > interceptor/propagator job.<br>
> ><br>
> > Do not use (temp at: 3) of handler (on:do:) as a marker of enablement<br>
> > (true) or temporary disablement (false) during handle block execution,<br>
> > since this is completely superseded by above mechanism. We should rather<br>
> > rename the (temp at: 3) as outerHandler and set it to nil.<br>
> > Since load order counts, and since some #on:do: context down the processes<br>
> > stacks are not going to die soon, we have equipped #handleSignal: with a<br>
> > workaround, so this change can wait.<br>
> ><br>
> > Attempt to preserve the possibility for an exception to<br>
> > rearmHandlerDuring: aBlock by temporarily resetting the outerHandler temp<br>
> > in the interceptorContext (which must be a new inst.var. recorded by the<br>
> > Exception).<br>
> ><br>
> > Alas, the #testHandlerReentrancy is now failing, because it expects an<br>
> > inner handler to be triggered by an exception raised from an outer handle<br>
> > block, which is forbidden by above implementation. This test is hardly<br>
> > compatible with testHandlerFromAction.<br>
> ><br>
> > I suggest adding an expected failure to document the change of behavior,<br>
> > and creating a new test demonstrating how rearmHandlerDuring: could be used.<br>
> > If we don't find a real interest in this message now that it cannot pass<br>
> > then intercept, we can as well deprecate it.<br>
> ><br>
> > =============== Diff against Kernel-cmm.855 ===============<br>
> ><br>
> > Item was changed:<br>
> > ----- Method: ContextPart>>canHandleSignal: (in category<br>
> > 'private-exceptions') -----<br>
> > canHandleSignal: exception<br>
> > "Sent to handler (on:do:) contexts only. If my exception class<br>
> > (first arg) handles exception then return true, otherwise forward this<br>
> > message to the next handler context. If none left, return false (see<br>
> > nil>>canHandleSignal:)"<br>
> ><br>
> > + ^ (((self tempAt: 1) handles: exception))<br>
> > - ^ (((self tempAt: 1) handles: exception) and: [self tempAt: 3])<br>
> > or: [self nextHandlerContext canHandleSignal: exception].<br>
> > !<br>
> ><br>
> > Item was changed:<br>
> > ----- Method: ContextPart>>handleSignal: (in category<br>
> > 'private-exceptions') -----<br>
> > handleSignal: exception<br>
> > + "Sent to handler (on:do:) and propagator (handleSignal:) contexts<br>
> > only.<br>
> > + If I am a handler (on:do:), and if my exception class (first arg)<br>
> > handles exception then execute my handle block (second arg), otherwise<br>
> > forward this message to the next handler context. If none left, execute<br>
> > exception's defaultAction (see nil>>handleSignal:).<br>
> > + If I am a propagator (handleSignal:) I just forward the handling<br>
> > to the outerHandler (temp at: 3). The propagator is allways above the<br>
> > handlers on the stack. If an exception occurs while executing the handle<br>
> > block, it will be intercepted by the propagator and redirected to the<br>
> > previously recorded outer handler, effectively bypassing all inner and<br>
> > current handler."<br>
> > - "Sent to handler (on:do:) contexts only. If my exception class<br>
> > (first arg) handles exception then execute my handle block (second arg),<br>
> > otherwise forward this message to the next handler context. If none left,<br>
> > execute exception's defaultAction (see nil>>handleSignal:)."<br>
> ><br>
> > + | val outerHandler |<br>
> > + <primitive: 199><br>
> > + (self tempAt: 3) == true ifTrue: [self tempAt: 3 put: nil].<br>
> > "preserve compatibility with old handlerContext"<br>
> > + ((self tempAt: 1) handles: exception) ifFalse: [<br>
> > + ^((self tempAt: 3) ifNil: [self nextHandlerContext])<br>
> > handleSignal: exception].<br>
> > +<br>
> > + exception privHandlerContext: self contextTag from: thisContext<br>
> > contextTag.<br>
> > + outerHandler := self nextHandlerContext. "disable self and all<br>
> > inner handlers while executing handle block"<br>
> > + val := (self tempAt: 2) cull: exception.<br>
> > - | val |<br>
> > - (((self tempAt: 1) handles: exception) and: [self tempAt: 3])<br>
> > ifFalse: [<br>
> > - ^ self nextHandlerContext handleSignal: exception].<br>
> > -<br>
> > - exception privHandlerContext: self contextTag.<br>
> > - self tempAt: 3 put: false. "disable self while executing handle<br>
> > block"<br>
> > - val := [(self tempAt: 2) cull: exception ]<br>
> > - ensure: [self tempAt: 3 put: true].<br>
> > self return: val. "return from self if not otherwise directed in<br>
> > handle block"<br>
> > !<br>
> ><br>
> > Item was added:<br>
> > + ----- Method: ContextPart>>rearmHandler:during: (in category<br>
> > 'private-exceptions') -----<br>
> > + rearmHandler: aHandlerContext during: aBlock<br>
> > + "Sent to interceptor (handleSignal:) contexts only, with a handler<br>
> > context (on:do:) parameter.<br>
> > + Makes aHandlerContext re-entrant for the duration of aBlock. Only<br>
> > works in a closure-enabled image"<br>
> > +<br>
> > + | oldHandler |<br>
> > + oldHandler := self tempAt: 3.<br>
> > + ^ [self tempAt: 3 put: aHandlerContext. aBlock value]<br>
> > + ensure: [self tempAt: 3 put: oldHandler]!<br>
> ><br>
> > Item was removed:<br>
> > - ----- Method: ContextPart>>rearmHandlerDuring: (in category<br>
> > 'private-exceptions') -----<br>
> > - rearmHandlerDuring: aBlock<br>
> > - "Sent to handler (on:do:) contexts only. Makes me re-entrant for<br>
> > the duration of aBlock. Only works in a closure-enabled image"<br>
> > -<br>
> > - ^ [self tempAt: 3 put: true. aBlock value]<br>
> > - ensure: [self tempAt: 3 put: false]!<br>
> ><br>
> > Item was changed:<br>
> > Object subclass: #Exception<br>
> > + instanceVariableNames: 'messageText tag signalContext<br>
> > handlerContext outerContext interceptorContext'<br>
> > - instanceVariableNames: 'messageText tag signalContext<br>
> > handlerContext outerContext'<br>
> > classVariableNames: ''<br>
> > poolDictionaries: ''<br>
> > category: 'Kernel-Exceptions-Kernel'!<br>
> ><br>
> > !Exception commentStamp: '<historical>' prior: 0!<br>
> > This is the main class used to implement the exception handling system<br>
> > (EHS). It plays two distinct roles: that of the exception, and that of<br>
> > the exception handler. More specifically, it implements the bulk of the<br>
> > protocols laid out in the ANSI specification - those protocol names are<br>
> > reflected in the message categories.<br>
> ><br>
> > Exception is an abstract class. Instances should neither be created nor<br>
> > trapped. In most cases, subclasses should inherit from Error or<br>
> > Notification rather than directly from Exception.<br>
> ><br>
> > In implementing this EHS, The Fourth Estate Inc. incorporated some ideas<br>
> > and code from Craig Latta's EHS. His insights were crucial in allowing us<br>
> > to implement BlockContext>>valueUninterruptably (and by extension, #ensure:<br>
> > and #ifCurtailed:), and we imported the following methods with little or no<br>
> > modification:<br>
> ><br>
> > ContextPart>>terminateTo:<br>
> > ContextPart>>terminate<br>
> > MethodContext>>receiver:<br>
> > MethodContext>>answer:<br>
> ><br>
> > Thanks, Craig!!!<br>
> ><br>
> > Item was removed:<br>
> > - ----- Method: Exception>>privHandlerContext: (in category 'priv<br>
> > handling') -----<br>
> > - privHandlerContext: aContextTag<br>
> > -<br>
> > - handlerContext := aContextTag!<br>
> ><br>
> > Item was added:<br>
> > + ----- Method: Exception>>privHandlerContext:from: (in category 'priv<br>
> > handling') -----<br>
> > + privHandlerContext: aContextTag from: anotherContextTag<br>
> > +<br>
> > + handlerContext := aContextTag.<br>
> > + interceptorContext := anotherContextTag!<br>
> ><br>
> > Item was changed:<br>
> > ----- Method: Exception>>rearmHandlerDuring: (in category 'handling')<br>
> > -----<br>
> > rearmHandlerDuring: aBlock<br>
> > "Make the current error handler re-entrant while it is running aBlock.<br>
> > Only works in a closure-enabled image"<br>
> ><br>
> > + ^ interceptorContext rearmHandler: handlerContext during: aBlock!<br>
> > - ^ handlerContext rearmHandlerDuring: aBlock!<br>
> ><br>
> ><br>
> ><br>
<br>
><br>
<br>
<br>
</div></div></blockquote></div></div></div><br></div></div>
</blockquote></div><br></div></div>