<div dir="ltr">Hi Nicolas,<div><br></div><div>I seem to have a Heisenbug now because of this:</div><div>In case you have the Git tools loaded, you should have a SquotImageStoreTest in your image. After loading this version and the follow-up fix versions of Kernel, the test SquotImageStoreTest>>testApplyPatch fails.</div><div><br></div><div>The test fails because an initialize method is not removed from the class to be patched. When the method is about to be MCMethodDefinition>>#unload-ed, it makes a CurrentEnvironment lookup in MCMethodDefiction>>actualClass, and it returns a wrong environment. It seems that the handler to set the dynamic Environment further up in the stack is not activated for this particular lookup. Yet if I debug through the procedure, everything works as it should. If I let the test run on its own, it fails.</div><div><br></div><div>But if I replace in MCMethodDefinition this:</div><div><br></div><div>actualClass<br>    ^ self actualClassIn: Environment current<br></div><div><br></div><div>by this:</div><div><br></div><div>actualClass</div><div>    Environment current.<br>    ^ self actualClassIn: Environment current<br></div><div><br></div><div>Then the test is suddenly green again. I suppose that is not acceptable. ;-)</div><div><br></div><div>It also works with Notification signal instead of the extraneous Environment current, so it seems like the signal handler stack is somehow in a wrong state, which is corrected by emitting an extraneous signal. And when I halt there to debug the situation, it also has to deal with extra signals, which corrects the state, so I cannot inspect the incorrect one. I didn't identify the reason for this behavior yet, so I am not sure whether my exception handling has bugs somewhere or whether Squeak's exception handling is bugged now.</div><div><br></div><div>Kind regards,</div><div>Jakob</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Am So., 11. Apr. 2021 um 19:33 Uhr schrieb <<a href="mailto:commits@source.squeak.org">commits@source.squeak.org</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Nicolas Cellier uploaded a new version of Kernel to project The Trunk:<br>
<a href="http://source.squeak.org/trunk/Kernel-nice.1384.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/trunk/Kernel-nice.1384.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Kernel-nice.1384<br>
Author: nice<br>
Time: 11 April 2021, 7:33:23.487481 pm<br>
UUID: ecb5db19-59bc-45f0-85d3-d9296a936a68<br>
Ancestors: Kernel-mt.1383<br>
<br>
Another attempt at fixing #testHandlerFromAction. Unlike previous attempts, this one preserves the expectations of #testHandlerReentrancy.<br>
<br>
The solution is to de-activate the handlers as we backtrack the stack, but to reactivate them before performing final exception handling actions (like resuming, resignalling or performing defaultAction). Indeed, those handlers must be able to handle a secondary exception raised in the course of this action.<br>
<br>
=============== Diff against Kernel-mt.1383 ===============<br>
<br>
Item was changed:<br>
  ----- Method: Context>>handleSignal: (in category 'private-exceptions') -----<br>
  handleSignal: exception<br>
        "Sent to handler (on:do:) contexts only.  If my exception class (first arg) handles exception<br>
         and the handler is active then execute my handle block (second arg), otherwise forward<br>
         this message to the next handler context.  If none left, execute exception's defaultAction<br>
         (see nil>>handleSignal:)."<br>
<br>
        | handlerActive val |<br>
        "If the context has been returned from the handlerActive temp var may not be accessible."<br>
        handlerActive := stackp >= 3 and: [(self tempAt: 3) == true].<br>
        (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse:<br>
+               [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. <br>
+               ^self nextHandlerContext handleSignal: exception].<br>
-               [^self nextHandlerContext handleSignal: exception].<br>
<br>
        exception privHandlerContext: self contextTag.<br>
        self tempAt: 3 put: false.  "disable self while executing handle block"<br>
        val := [(self tempAt: 2) cull: exception]<br>
+                       ifCurtailed: [self tempAt: 3 put: true].<br>
-                       ensure: [self tempAt: 3 put: true].<br>
        self return: val  "return from self if not otherwise directed in handle block"<br>
  !<br>
<br>
Item was added:<br>
+ ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') -----<br>
+ reactivateHandlers<br>
+       "Private - sent to exception handler context only (on:do:).<br>
+       Reactivate all the handlers into the chain"<br>
+       <br>
+       self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:"<br>
+       self nextHandlerContext reactivateHandlers!<br>
<br>
Item was added:<br>
+ ----- Method: Exception>>reactivateHandlers (in category 'priv handling') -----<br>
+ reactivateHandlers<br>
+       "reactivate all the exception handlers in the context chain"<br>
+       self canSearchForSignalerContext<br>
+               ifTrue: [signalContext nextHandlerContext reactivateHandlers]!<br>
<br>
Item was changed:<br>
  ----- Method: Exception>>resignalAs: (in category 'handling') -----<br>
  resignalAs: replacementException<br>
        "Signal an alternative exception in place of the receiver."<br>
<br>
+       self reactivateHandlers.<br>
        self resumeUnchecked: replacementException signal!<br>
<br>
Item was changed:<br>
  ----- Method: UndefinedObject>>handleSignal: (in category 'bottom context') -----<br>
  handleSignal: exception<br>
+       "When no more handler (on:do:) context left in sender chain this gets called.  Return from signal with default action.<br>
+       Before doing that, reactivate the handlers so that they can catch eventual secondary exceptions raised by defaultAction."<br>
-       "When no more handler (on:do:) context left in sender chain this gets called.  Return from signal with default action."<br>
<br>
+       ^ exception reactivateHandlers; resumeUnchecked: exception defaultAction!<br>
-       ^ exception resumeUnchecked: exception defaultAction!<br>
<br>
Item was added:<br>
+ ----- Method: UndefinedObject>>reactivateHandlers (in category 'bottom context') -----<br>
+ reactivateHandlers<br>
+       "nothing to do for bottom context"<br>
+       <br>
+       ^ self!<br>
<br>
<br>
</blockquote></div>