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