<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">Hi Christophe,</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Dec 13, 2019 at 10:48 AM Thiede, Christoph <<a href="mailto:Christoph.Thiede@student.hpi.uni-potsdam.de">Christoph.Thiede@student.hpi.uni-potsdam.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">




<div dir="ltr">
<div id="gmail-m_-893075213057209812divtagdefaultwrapper" dir="ltr" style="font-size:12pt;color:rgb(0,0,0);font-family:Calibri,Helvetica,sans-serif,EmojiFont,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Segoe UI Symbol","Android Emoji",EmojiSymbols">
<p>Hi all,</p>
<p><br>
</p>
<p>I discovered a bug when stepping over a call to Generator >> #nextPut:.</p></div></div></blockquote><div><br></div><div>Apologies.  I can now reproduce the bug.  I was stupidly stepping over the block evaluation, not the send of nextPut:.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div id="gmail-m_-893075213057209812divtagdefaultwrapper" dir="ltr" style="font-size:12pt;color:rgb(0,0,0);font-family:Calibri,Helvetica,sans-serif,EmojiFont,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Segoe UI Symbol","Android Emoji",EmojiSymbols">
<p>!! Save your image before trying the following !!</p>
<p><br>
</p>
<p></p>
<div>Generator</div>
<div><span style="white-space:pre-wrap"></span>on: [:stream | stream <span style="background-color:rgb(190,190,190)">
nextPut: #foo</span>]</div>
<br>
<p></p>
<p><img size="43800" id="gmail-m_-893075213057209812img765834" style="max-width: 99.9%;" src="cid:16f35ae515df456b1e51"><br>
</p>
<p><br>
</p>
<p></p>
<ol style="margin-bottom:0px;margin-top:0px">
<li>Due to multiprocessing implementation of the Generator, pressing over will hang up the current process forever, because the generator is never queried.</li><li>If I press cmd-dot, I get an infinite number of debugger windows that show Context >> #<span>cannotReturn:. This will probably damage your image.</span></li></ol>
<div><br>
</div>
<div>The first is annoying for newcomers, but I see this behavior is reasonable and without the effect of the second, it wouldn't be a big problem.</div>
<div>The second, however, looks like a bigger issue to me. Actually, I think the most serious aspect is that in Squeak 5.1, the same procedure does not crash your image, but you are forwarded to the emergency debugger and can terminate the process:</div>
<div><br>
</div>
<div><img size="185254" id="gmail-m_-893075213057209812img183784" height="180" width="263" src="cid:16f35ae515df456b1e52"> <img size="171961" id="gmail-m_-893075213057209812img805985" height="180" width="263" src="cid:16f35ae515df456b1e53"><br>
</div>
<div><br>
</div>
<div>Also, this is not the first scenario <span style="font-family:Calibri,Helvetica,sans-serif,EmojiFont,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Segoe UI Symbol","Android Emoji",EmojiSymbols;font-size:16px">
in the last time </span>where I got an infinite debugger chain. See <span><a href="http://forum.world.st/BUG-s-in-Context-control-jump-runUntilErrorOrReturnFrom-td5107263.html" target="_blank">[BUG(s)] in Context control (#jump, #runUntilErrorOrReturnFrom:)</a> for
 a similar issue. And there were even more situations which I could not yet reproduce exactly.</span></div>
<div><span>I'm afraid that the recent changes to the debuggers might have weakened its ability to detect recursive errors. Can someone else tell about these problems?</span></div>
<div><span><br>
</span></div>
<div><span>I suppose we ignore a large number of recursive errors as in MorphicDebugger >> #<span>openOn:context:label:contents:fullView:, the uiBlock is often triggered as a separate UI message which will be executed after the recursion flag has been cleared
 by the base class.</span></span></div>
<div><span><span><br>
</span></span></div>
<div><span><span>Would be great if someone could have a look at it or share more information :)</span></span></div></div></div></blockquote><div><br></div><div>So the issue seems to me to be the interaction between the block established in runUntilErrorOrReturnFrom: to catch unhandled errors (this one:</div><div><div>Context contextOn: UnhandledError do: [:ex |</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                 </span>error ifNil: [</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                         </span>error := ex exception.</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                         </span>topContext := thisContext.</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                             </span>ex resumeUnchecked: here jump]</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                 </span>ifNotNil: [ex pass]</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">            </span>]</div></div><div>)</div><div>and the swapSender: in Generator>>nextPut:.  So after the swapSender: the Generator's continue variable refers to this BlockClosure>>on:do:. BlockClosure>>ensure: pair introduced by runUntilErrorOrReturnFrom:.  What I don't understand was how the evaluateOnBehalfOf: changes interact with that.  But what I can say is that the Debugger is leaving the Generator (or any code that uses swapSender:) in an invalid state because </div><div>a) once the swapSender: occurs the protect blocks (the on:do:,ensure: pair) are no longer on the stack.  What the swapSender should have been morphed into doing was preserving the protect blocks under the current context, or rather that swapSender should have been persuaded to swap the senders of the protect blocks.  Now when the debugger continues stepping it never gets to the protect blocks because they have been swapped out of the way, and execution proceeds all the way down to the fork in Generator>>reset.</div><div><br></div><div>You can observe this by</div><div>- stepping through "Generator on: [:stream | stream nextPut: #foo]" until at the send of #nextPut:</div><div>- inspecting the Debugger (via the Morphic tool handle menu "inspect model"</div><div>- debugging "self doStep" to step the Debugger through the send</div><div>- when you get to runUntilErrorOrReturnFrom: *ONLY STEP UP TO THE jump* *DO NOT STEP OVER THE jump*</div><div>- at the jump, step into, then do step into, and you'll find the debugger now in Generator>>nextPut:, with the stack still including the protect pair.  But when you step over the swapSender: then, of course, they've gone missing, and the stack points back to the fork in reset with nothing on the stack to stop execution (because there's no ensure: block which is what runUntilErrorOrReturnFrom: inserted to try and catch any attempt to return).</div><div><br></div><div>So to get to the point of the swapSender: you should see this:</div><div><br></div><div><div>Context>>jump</div><div>Context>>runUntilErrorOrReturnFrom:</div><div>[] in Process>>complete:</div><div>BlockClosure>>ensure:</div><div>Process>>evaluate:onBehalfOf:</div><div>Process>>complete:</div><div>Process>>completeStep:</div><div>[] in MorphicDebugger(Debugger)>>doStep</div><div>BlockClosure>>on:do:</div><div>MorphicDebugger(Debugger)>>handleLabelUpdatesIn:whenExecuting:</div><div>MorphicDebugger(Debugger)>>doStep</div></div><div><br></div><div>and the stack from the Context about to jump is</div><div><br></div><div>Generator>>nextPut:</div><div>BlockClosure>>on:do:</div><div>BlockClosure>>ensure:</div><div>[] in UndefinedObject>>DoIt</div><div>Generator>>fork</div><div>[] in Generator>>reset</div><div>Generator>>reset</div><div>Generator>>initializeOn:</div><div>Generator class>>on:</div><div>UndefinedObject>>DoIt ...<br></div><div><br></div><div>and the Generator's "continue" stack immediately before the swapSender: in Generator>>nextPut: is</div><div><br></div><div>Generator>>reset</div><div>Generator>>initializeOn:</div><div>Generator class>>on:</div><div>UndefinedObject>>DoIt<br></div><div><br></div><div>What we'd like to see after the swapSender: is the protect blocks moved to the continue stack:</div><div>Generator>>nextPut:</div><div>BlockClosure>>on:do:</div><div>BlockClosure>>ensure:<br></div><div>Generator>>reset</div><div>Generator>>initializeOn:</div><div>Generator class>>on:</div><div>UndefinedObject>>DoIt<br></div><div><br></div><div>and the new "continue" stack looking like this:</div><div><div>Generator>>fork</div><div>[] in Generator>>reset</div><div>Generator>>reset</div><div>Generator>>initializeOn:</div><div>Generator class>>on:</div><div>UndefinedObject>>DoIt ...</div></div><div><br></div><div><br></div><div>What I don't know is how to fix this in the general case.  This seems hard.  The debugger is executing Smalltalk (i.e. *not* stepping bytecodes) in the context of runUntilErrorOrReturnFrom: and a swapSender: could happen at an arbitrarily deep point in that execution and we want the protect blocks in runUntilErrorOrReturnFrom: to protect execution after a swapSender:.  I have no idea how to do that.</div><div><br>Now what's more likely is that I'm not seeing what's obviously wrong about the introduction of evaluate:onBehalfOf:.  Why does this make any difference?  It seems to me that the issue is with runUntilErrorOrReturnFrom: and swapSender:, not with evaluate:onBehalfOf:.  What am I missing?<br><br>> Best,<br>> Christoph<br><br></div></div><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div>