<div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-size:small"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Nov 29, 2021 at 1:46 AM <<a href="mailto:mail@jaromir.net">mail@jaromir.net</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">Hi Eliot, all,<br>
<br>
> This looks good. The one thing I find concerning is running terminate in a different process.  Various idioms could legitimately require an unwind block to run in the process in which it was created.  At the very least shouldn't the effectiveProcess be set to be that of the process that is terminating while its unwind block executes?<br>
><br>
> For example, what if I did something like this:<br>
> doWhileMonitoring: aBlock<br>
>     monitoredProcesses add: Processor activeProcess.<br>
>     ^aBlock ensure: [monitoredProcesses remove:: Processor activeProcess ifAbsent: []]<br>
<br>
Would this test prove #terminate works as you'd expect?<br>
```<br>
    | q |<br>
    [<br>
      [q := Processor activeProcess.<br>
      Processor activeProcess suspend] ensure: [<br>
        self assert: q = Processor activeProcess]<br>
    ] fork.<br>
    Processor yield.<br>
    q terminate<br>
```<br></blockquote><div><br></div><div class="gmail_default" style="font-size:small">Yes, that captures it.</div><div class="gmail_default" style="font-size:small"></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">
Or with a raised exception:<br>
```<br>
    | q |<br>
    [<br>
        [q := Processor activeProcess.<br>
        self error] ensure: [<br>
                self assert: q = Processor activeProcess]<br>
    ] fork.<br>
    Processor yield.<br>
```<br>
(If I remove #evaluate:onBehalfOf: from #complete:to: both tests fail, indeed)<br>
<br>
Please let me know if this is acceptable.<br></blockquote><div><br></div><div class="gmail_default" style="font-size:small">ish. The reason I thought you weren't setting the effective process is that it's buried in complete:to:.  I'd rather see it up front in Process>>terminate itself.  But I'm happy to defer to you; you've done the work :-)</div><div class="gmail_default" style="font-size:small"><br></div><div class="gmail_default" style="font-size:small"><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">
<br>
Thanks again, </blockquote><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">
<br>
<br>
^[^ Jaromir<br>
  --<br>
<br>
Sent from Squeak Inbox Talk<br>
<br>
On 2021-11-28T22:57:25+01:00, <a href="mailto:mail@jaromir.net" target="_blank">mail@jaromir.net</a> wrote:<br>
<br>
> Hi Eliot,<br>
> <br>
> thanks very much for reviewing this.<br>
> <br>
> > This looks good. The one thing I find concerning is running terminate in a different process.  Various idioms could legitimately require an unwind block to run in the process in which it was created.  <br>
> <br>
> Frankly, I haven't explicitly considered that... In the worst case we could revert active process termination bit like it was. Terminating an active process via a different process was just supposed to unify (and extend) the termination semantics.<br>
> <br>
> > At the very least shouldn't the effectiveProcess be set to be that of the process that is terminating while its unwind block executes?<br>
> <br>
> That's what I though I did in Process>>#complete: topContext to: aContext <br>
> <br>
> [...]<br>
>       pair := Processor activeProcess<br>
>                               evaluate: [topContext runUnwindUntilErrorOrReturnFrom: aContext]<br>
>                               onBehalfOf: self.<br>
> [...]<br>
> <br>
> where self is the process being terminated. #runUnwindUntilErrorOrReturnFrom: jumps to the stack of the process being terminated and executes the unwind block with effective process set to the process being terminated. <br>
> <br>
> Or am I mistaken?<br>
> <br>
> >  For example, what if I did something like this:<br>
> > doWhileMonitoring: aBlock<br>
> >     monitoredProcesses add: Processor activeProcess.<br>
> >     ^aBlock ensure: [monitoredProcesses remove:: Processor activeProcess ifAbsent: []]<br>
> ><br>
> > That unwind blocks are run in the same process as they were created seems to me to be a legitimate expectation. Can this be reengineered maintaining this invariant, or at least setting the effective process to be that of the process being terminated?<br>
> <br>
> This is a very interesting example - thanks! Running terminate in a different process allows to relatively easily identify all unwind blocks half-way through their execution and complete them. In case setting the effective process in #complete:to: doesn't work as you requested, then I'm afraid unwinding blocks half-way through their execution would be very hard to achieve from the process being terminated itself (not impossible though - I tried but then doubted it was worth the effort). Or theoretically, it might be possible to maintain two stacks for the process being terminated - one "original" that needs to be unwound and a second "helper" one running terminate - but I haven't gotten beyond the idea, it seemed too unchartered :)<br>
> <br>
> Besides, when an error happens during unwind, a debugger opens and the identity of the process running terminate may change, so the invariant may not survive the first error anyway (at least in what I was considering).<br>
> <br>
> > So instead of<br>
> ><br>
> >     self isActiveProcess ifTrue: [<br>
> >         [self terminate] fork.<br>
> >         ^self suspend].<br>
> ><br>
> > we would use<br>
> ><br>
> >     self isActiveProcess ifTrue:<br>
> >         [| arnold |<br>
> >         arnold := [arnold evaluate: [self terminate] onBehalfOf: self] newProcess.<br>
> >         arnold resume.<br>
> >         ^self suspend].<br>
> ><br>
> <br>
> No, that wouldn't work because the Terminator identifies itself as the process being terminated when executing [self terminate] resulting in an infinite loop.<br>
> <br>
> At the moment I can't see why setting the effective process in #complete:to: wouldn't suffice but I'll get there :) I'll try to come up with a test.<br>
> <br>
> I'm intrigued: why did you use '[arnold evaluate:...' and not '[Processor activeProcess evaluate:...'; I can't figure out the difference :)<br>
> <br>
> > I might also consider discarding the return of suspend, because it shouldn't be executed normally, and using, say<br>
> ><br>
> > ```<br>
> > self isActiveProcess ifTrue:<br>
> >     [| arnold |<br>
> >     arnold := [arnold evaluate: [self terminate] onBehalfOf: self] newProcess.<br>
> >     arnold resume.<br>
> >     self suspend.<br>
> >     self error: 'error in terminate; execution resumed after suspend for termination'].<br>
> > ```<br>
> <br>
> No, this wouldn't work if Processor activeProcess terminate was inside an unwind block. Terminate would attempt to proceed after self suspend and would always raise the error.<br>
> <br>
> Thanks again,<br>
> <br>
> Jaromir<br>
> <br>
> PS: I used this example to test your suggestions:<br>
> <br>
> ```<br>
> | p |<br>
> p := [<br>
>       [<br>
>               [ ] ensure: [<br>
>                       [Processor activeProcess terminate] ensure: [<br>
>                               Transcript show: 'x1']. <br>
>                       Transcript show: 'x2']<br>
>       ] ensure: [<br>
>               Transcript show: 'x3'].<br>
>       Transcript show: 'x4'<br>
> ] newProcess.<br>
> p resume.<br>
> "Two yields necessary: terminate active is a two-step procedure"<br>
> Processor yield. Processor yield.<br>
> Transcript show: p isTerminated printString<br>
> <br>
> "prints x1 x2 x3"<br>
> ```<br>
> <br>
> <br>
> ^[^ Jaromir<br>
>   --<br>
> <br>
> Sent from Squeak Inbox Talk<br>
> <br>
> On 2021-11-28T10:52:41-08:00, eliot.miranda at <a href="http://gmail.com" rel="noreferrer" target="_blank">gmail.com</a> wrote:<br>
> <br>
> > Hi Jaromir, Hi Christoph,<br>
> > <br>
> > On Sat, Nov 27, 2021 at 12:12 PM <mail at <a href="http://jaromir.net" rel="noreferrer" target="_blank">jaromir.net</a>> wrote:<br>
> > <br>
> > > Hi all, Christoph,<br>
> > ><br>
> > > I finally managed to separate #terminate and the 'block cannot return<br>
> > > issue' so that we can discuss them independently :) And thanks to Eliot's<br>
> > > solution of the infinite recursion in #doesNotUnderstand the #terminate<br>
> > > code is now cleaner. I haven't included Eliot's modification of<br>
> > > #doesNotUnderstand in my changeset but paste it below instead (because I'm<br>
> > > not the author; I hope it'll be merged though):<br>
> > ><br>
> > > The #terminate code presented in Kernel-jar.1426 is the final version of<br>
> > > my effort to get rid of all the bugs reported in this thread (and make<br>
> > > #terminate semantics more consistent). It passes all standard tests and the<br>
> > > tests complementing this changeset:<br>
> > ><br>
> > > KernelTests-jar.406 (Terminator test)<br>
> > > KernelTests-jar.407 (McClure test)<br>
> > > Tests-jar.466 (unwind tests)<br>
> > > ToolsTests-jar.105 (debugger tests)<br>
> > ><br>
> > > In addition, it's fully compatible with Christoph's solution of the 'block<br>
> > > cannot return issue' presented in Kernel-ct.1405 (<br>
> > > <a href="http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-May/215526.html" rel="noreferrer" target="_blank">http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-May/215526.html</a>).<br>
> > ><br>
> > ><br>
> > > Summary and discussion about the bugs and changes in #terminate:<br>
> > > <a href="http://forum.world.st/Solving-multiple-termination-bugs-summary-amp-proposal-td5128285.html" rel="noreferrer" target="_blank">http://forum.world.st/Solving-multiple-termination-bugs-summary-amp-proposal-td5128285.html</a><br>
> > ><br>
> > > I think it's ready for merging... Please review.<br>
> > ><br>
> > <br>
> > This looks good. The one thing I find concerning is running terminate in a<br>
> > different process.  Various idioms could legitimately require an unwind<br>
> > block to run in the process in which it was created.  At the very least<br>
> > shouldn't the effectiveProcess be set to be that of the process that is<br>
> > terminating while its unwind block executes?<br>
> > <br>
> > For example, what if I did something like this:<br>
> > doWhileMonitoring: aBlock<br>
> >     monitoredProcesses add: Processor activeProcess.<br>
> >     ^aBlock ensure: [monitoredProcesses remove:: Processor activeProcess<br>
> > ifAbsent: []]<br>
> > <br>
> > That unwind blocks are run in the same process as they were created seems<br>
> > to me to be a legitimate expectation. Can this be reengineered maintaining<br>
> > this invariant, or at least setting the effective process to be that of the<br>
> > process being terminated?<br>
> > <br>
> > So instead of<br>
> > <br>
> >     self isActiveProcess ifTrue: [<br>
> >         [self terminate] fork.<br>
> >         ^self suspend].<br>
> > <br>
> > we would use<br>
> > <br>
> >     self isActiveProcess ifTrue:<br>
> >         [| arnold |<br>
> >         arnold := [arnold evaluate: [self terminate] onBehalfOf: self]<br>
> > newProcess.<br>
> >         arnold resume.<br>
> >         ^self suspend].<br>
> > <br>
> > I might also consider discarding the return of suspend, because it<br>
> > shouldn't be executed normally, and using, say<br>
> > <br>
> >     self isActiveProcess ifTrue:<br>
> >         [| arnold |<br>
> >         arnold := [arnold evaluate: [self terminate] onBehalfOf: self]<br>
> > newProcess.<br>
> >         arnold resume.<br>
> >         self suspend.<br>
> >         self error: 'error in terminate; execution resumed after suspend<br>
> > for termination'].<br>
> > <br>
> > <br>
> > > --<br>
> > > Eliot's fix of infinite recursion in doesNotUnderstand:<br>
> > ><br>
> > ><br>
> > > doesNotUnderstand: aMessage<br>
> > >          "Handle the fact that there was an attempt to send the given<br>
> > >           message to the receiver but the receiver does not understand<br>
> > >           this message (typically sent from the machine when a message<br>
> > >          is sent to the receiver and no method is defined for that<br>
> > > selector)."<br>
> > ><br>
> > >         "Testing: (3 activeProcess)"<br>
> > ><br>
> > >         | exception resumeValue |<br>
> > >         (exception := MessageNotUnderstood new)<br>
> > >                 message: aMessage;<br>
> > >                 receiver: self.<br>
> > >         resumeValue := exception signal.<br>
> > >         ^exception reachedDefaultHandler<br>
> > >                 ifFalse: [resumeValue]<br>
> > > "----------> this wrapper detecting recursion is added:  -------------->"<br>
> > ><br>
> > >                 ifTrue: [<br>
> > >                         [aMessage sentTo: self]<br>
> > >                                 on: MessageNotUnderstood<br>
> > >                                 do: [:ex| | args |<br>
> > >                                        args := ex message arguments.<br>
> > >                                        (ex receiver == self<br>
> > >                                        and: [ex message selector ==<br>
> > > aMessage selector<br>
> > >                                         and: [(1 to: aMessage numArgs)<br>
> > > allSatisfy: [:i| (args at: i) == (aMessage argumentAt: i)]]]) ifFalse:<br>
> > >                                        [ex pass].<br>
> > >                                     self error: 'infinite recursion in<br>
> > > doesNotUnderstand:']]<br>
> > ><br>
> > > (see discussion<br>
> > > <a href="http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-November/217031.html" rel="noreferrer" target="_blank">http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-November/217031.html</a><br>
> > > )<br>
> > ><br>
> > > best,<br>
> > ><br>
> > > ^[^ Jaromir<br>
> > >   --<br>
> > ><br>
> > > Sent from Squeak Inbox Talk<br>
> > ><br>
> > > On 2021-11-17T18:49:44+01:00, mail at <a href="http://jaromir.net" rel="noreferrer" target="_blank">jaromir.net</a> wrote:<br>
> > ><br>
> > > > Hi Christoph,<br>
> > > ><br>
> > > > Once more, apologies for taking so long to respond.<br>
> > > ><br>
> > > > > > [...] there really are two distinct unwind semantics : one "light"<br>
> > > for regular returns and one "heavy" for termination. Both are very similar<br>
> > > yet each require a slightly different behavior - that's why the duality<br>
> > > #runUntilErrorOrReturnFrom / #runUnwindUntilErrorOrReturnFrom or #complete:<br>
> > > / #complete:to: and #unwindTo: / #terminate.<br>
> > > > ><br>
> > > > > But they are still pretty similar ... Couldn't you just add some extra<br>
> > > parameter to these message? E.g., "Context runUntilErrorOrReturnFrom:<br>
> > > aggressive"? I have the feeling that we could eliminate significant<br>
> > > duplication that way by inserting some ifs and elses ... Duplicated code<br>
> > > very often tends to be harder to maintained.<br>
> > > ><br>
> > > > Yes, I understand your concern and agree two ifs would allow to pack the<br>
> > > two twin beasts into one can (I refer to "rueorf" & "ruueorf"). Also, we<br>
> > > could consider Process >> complete:to: as a generalized version of Process<br>
> > > >> complete and rewrite it accordingly. This is doable, maybe even<br>
> > > desirable but for the time being I'd very much prefer to keep them separate<br>
> > > to facilitate troubleshooting of potential problems (or localizing them).<br>
> > > Each of the two similar methods belong to a different execution path after<br>
> > > all. And besides, #runUntilErrorOrReturnFrom is already crazy enough and I<br>
> > > don't feel like making it even more complex now :)<br>
> > > ><br>
> > > > > > With regards to #unwindTo: - I haven't tested it yet but I'm<br>
> > > wondering whether it wouldn't have the same unwind problem with non-local<br>
> > > returns as the original #terminate and require a similar fix?<br>
> > > > ><br>
> > > > > Hm, do we need to implement both modi - (ii) and (iii) as described in<br>
> > > [1] - in Context >> #unwindTo: as well? Something like<br>
> > > #unwindTo:aggressive:?<br>
> > > ><br>
> > > > I put #unwindTo: aside for the moment; it contains the same flaw and<br>
> > > deserves its own thread.<br>
> > > ><br>
> > > > > Unfortunately I've lost track of these infinite loops [...]<br>
> > > ><br>
> > > > Yeah, tell me about it :)<br>
> > > ><br>
> > > > > [...]- could you maybe point me to some concrete examples that lead to<br>
> > > an infinite recursion without this special check? :-)<br>
> > > ><br>
> > > > Try:<br>
> > > ><br>
> > > > ```<br>
> > > > [self error: 'error'] ensure: [self gotcha. Transcript show: 'all<br>
> > > cleaned up! ']<br>
> > > > ```<br>
> > > ><br>
> > > > 'gotcha' represents a method unknown to the system. The code will print<br>
> > > 'all cleaned up! ' after abandoning the error and the debugger - meaning<br>
> > > the system will survive this code and execute all cleanups (aka unwinds).<br>
> > > In case you use your #terminateAggressively as the default action for<br>
> > > abandoning the Debugger, you won't have any problem of course because you<br>
> > > skip completing the halfway through unwind. What I'm saying is: even if you<br>
> > > chose the classic heavy #terminate to exit the Debugger, the code will<br>
> > > execute remaining unwinds as one might expect (or hope for).<br>
> > > ><br>
> > > > > One more question about your #runUnwindUntilErrorOrReturnFrom: Are you<br>
> > > maybe missing something like "cxt terminate" in the "No error was raised"<br>
> > > case? Just wondering.<br>
> > > ><br>
> > > > I guess I know what you mean... 'ctxt' would get garbage collected soon<br>
> > > anyway so I left it as is to keep the code as simple as possible.<br>
> > > ><br>
> > > ><br>
> > > ><br>
> > > > Christoph, I'll also address your comments regarding the<br>
> > > BlockCannotReturn behavior here:<br>
> > > ><br>
> > > > > Isn't that ProceedBlockCannotReturn tautologous? I think that by<br>
> > > actively proceeding from a BlockCannotReturn error users already accept<br>
> > > that they are going to resume execution in another way.<br>
> > > ><br>
> > > > Well, the very proceeding from a BlockCannotReturn error sort of<br>
> > > violates common sense but during our lengthy discussion you convinced me it<br>
> > > makes a very good sense when troubleshooting :) The idea is by no means<br>
> > > trivial - unlike hitting Proceed :) So an extra warning can't hurt...<br>
> > > ><br>
> > > > But more importantly, I need something to know the user let the process<br>
> > > continue after reaching the BlockCannotReturn error - thus the new<br>
> > > ProceedBlockCannotReturn exception which allows Process >> #complete:to: to<br>
> > > deal with the new course of events.<br>
> > > ><br>
> > > > > Apart from that, the message text of your new warning is not correct<br>
> > > if self pc <= self endPC. :-)<br>
> > > ><br>
> > > > Yes, and I'd like to make the warning message more verbose so even if<br>
> > > someone hit Proceed without much thinking they could get an idea what's<br>
> > > about to happen :) Should the warning interfere with some potential<br>
> > > automation efforts we could come up with some alternative way.<br>
> > > ><br>
> > > > I'll copy my reply regarding BCR to the "The Inbox: Kernel-ct.1405.mcz"<br>
> > > thread and we can continue discussing this particular issue there. It's<br>
> > > really a separate issue and I included your patch here along with the main<br>
> > > termination code because it perfectly complements it and prevents the<br>
> > > disastrous crashes caused by Proceeding the BCR error.<br>
> > > ><br>
> > > > > [...] the computation terminated is also wrong, IMO, you should get a<br>
> > > BlockCannotReturn here.<br>
> > > ><br>
> > > > Yes, I agree, there's definitely more to it which deserves to be<br>
> > > discussed thoroughly and separately in the "The Inbox: Kernel-ct.1405.mcz"<br>
> > > thread.<br>
> > > ><br>
> > > > If you agree I'd really appreciate if your fix could be accepted here in<br>
> > > including the ProceedBlockCannotReturn exception I need to make it work<br>
> > > together with the code I'm presenting here. If we come up with a better<br>
> > > idea in the other discussion we can make amends here as well; I take it as<br>
> > > a patch, not a definitive solution :)<br>
> > > ><br>
> > > > Thanks again so much for all your suggestions and examples! It's always<br>
> > > a pleasure :) Plus - the Inbox Talk is priceless... I use it exclusively<br>
> > > now and look forward to any improvements you might come up in the future ;)<br>
> > > ><br>
> > > > Best,<br>
> > > ><br>
> > > ><br>
> > > > ^[^ Jaromir<br>
> > > >   --<br>
> > > ><br>
> > > > Sent from Squeak Inbox Talk<br>
> > > ><br>
> > > > On 2021-08-22T16:49:10+02:00, christoph.thiede at<br>
> > > <a href="http://student.hpi.uni-potsdam.de" rel="noreferrer" target="_blank">student.hpi.uni-potsdam.de</a> wrote:<br>
> > > ><br>
> > > > > Hi Jaromir,<br>
> > > > ><br>
> > > > > > Yes, I was wondering why I couldn't get rid of the duplication and<br>
> > > now I think it's because there really are two distinct unwind semantics :<br>
> > > one "light" for regular returns and one "heavy" for termination. Both are<br>
> > > very similar yet each require a slightly different behavior - that's why<br>
> > > the duality #runUntilErrorOrReturnFrom / #runUnwindUntilErrorOrReturnFrom<br>
> > > or #complete: / #complete:to: and #unwindTo: / #terminate.<br>
> > > > ><br>
> > > > > But they are still pretty similar ... Couldn't you just add some extra<br>
> > > parameter to these message? E.g., "Context runUntilErrorOrReturnFrom:<br>
> > > aggressive"? I have the feeling that we could eliminate significant<br>
> > > duplication that way by inserting some ifs and elses ... Duplicated code<br>
> > > very often tends to be harder to maintained.<br>
> > > > ><br>
> > > > > > With regards to #unwindTo: - I haven't tested it yet but I'm<br>
> > > wondering whether it wouldn't have the same unwind problem with non-local<br>
> > > returns as the original #terminate and require a similar fix?<br>
> > > > ><br>
> > > > > Hm, do we need to implement both modi - (ii) and (iii) as described in<br>
> > > [1] - in Context >> #unwindTo: as well? Something like<br>
> > > #unwindTo:aggressive:?<br>
> > > > ><br>
> > > > > > But in general - yes, any method/exception purposefully (or not)<br>
> > > written to create a loop will break this patch (I admit it is just a patch<br>
> > > really). I extracted it to #complete:to: to make #terminate clean; this is<br>
> > > a WIP; I wish there was a holistic solution to this - maybe checking for<br>
> > > exception recursion by default? :)<br>
> > > > ><br>
> > > > > Sounds better already, if feasible! But how would you detect this?<br>
> > > Unfortunately I've lost track of these infinite loops - could you maybe<br>
> > > point me to some concrete examples that lead to an infinite recursion<br>
> > > without this special check? :-)<br>
> > > > ><br>
> > > > > One more question about your #runUnwindUntilErrorOrReturnFrom: Are you<br>
> > > maybe missing something like "cxt terminate" in the "No error was raised"<br>
> > > case? Just wondering.<br>
> > > > ><br>
> > > > > Best,<br>
> > > > > Christoph<br>
> > > > ><br>
> > > > > [1]<br>
> > > <a href="http://forum.world.st/The-semantics-of-halfway-executed-unwind-contexts-during-process-termination-tp5129800p5130110.html" rel="noreferrer" target="_blank">http://forum.world.st/The-semantics-of-halfway-executed-unwind-contexts-during-process-termination-tp5129800p5130110.html</a><br>
> > > > ><br>
> > > > > ---<br>
> > > > > Sent from Squeak Inbox Talk<br>
> > > > ><br>
> > > > > On 2021-05-31T17:01:46-05:00, m at <a href="http://jaromir.net" rel="noreferrer" target="_blank">jaromir.net</a> wrote:<br>
> > > > ><br>
> > > > > > Jaromir Matas wrote<br>
> > > > > > > Hi All,<br>
> > > > > > > I've sent an updated version of #teminate integrating Christoph's<br>
> > > solution<br>
> > > > > > > of BlockCannotReturn recursion problem (in [1]), along with a<br>
> > > battery of<br>
> > > > > > > tests exploring termination of nested ensure and cascading errors<br>
> > > behavior<br>
> > > > > > > (Debugger tests are for info and a final version can wait until<br>
> > > releasing<br>
> > > > > > > Christoph's proposal in [2]).<br>
> > > > > > ><br>
> > > > > > > It's pretty much final, I hope...<br>
> > > > > > ><br>
> > > > > > > Any complaints about #terminate - please shout ;)<br>
> > > > > > ><br>
> > > > > > > [1]<br>
> > > <a href="http://forum.world.st/The-Inbox-Kernel-ct-1405-mcz-td5129706.html" rel="noreferrer" target="_blank">http://forum.world.st/The-Inbox-Kernel-ct-1405-mcz-td5129706.html</a><br>
> > > > > > > [2]<br>
> > > > > > ><br>
> > > <a href="http://forum.world.st/The-semantics-of-halfway-executed-unwind-contexts-during-process-termination-tp5129800p5130110.html" rel="noreferrer" target="_blank">http://forum.world.st/The-semantics-of-halfway-executed-unwind-contexts-during-process-termination-tp5129800p5130110.html</a><br>
> > > > > > ><br>
> > > > > > > best,<br>
> > > > > ><br>
> > > > > > Here's the link:<br>
> > > > > > <a href="http://forum.world.st/The-Inbox-Kernel-jar-1414-mcz-td5130198.html" rel="noreferrer" target="_blank">http://forum.world.st/The-Inbox-Kernel-jar-1414-mcz-td5130198.html</a><br>
> > > > > ><br>
> > > > > ><br>
> > > > > ><br>
> > > > > > -----<br>
> > > > > > ^[^ Jaromir<br>
> > > > > > --<br>
> > > > > > Sent from: <a href="http://forum.world.st/Squeak-Dev-f45488.html" rel="noreferrer" target="_blank">http://forum.world.st/Squeak-Dev-f45488.html</a><br>
> > > > > ><br>
> > > > > ><br>
> > > > > -------------- next part --------------<br>
> > > > > An HTML attachment was scrubbed...<br>
> > > > > URL: <<br>
> > > <a href="http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20210822/9adf7f0d/attachment.html" rel="noreferrer" target="_blank">http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20210822/9adf7f0d/attachment.html</a><br>
> > > ><br>
> > > > ><br>
> > > > ><br>
> > > ><br>
> > > ><br>
> > ><br>
> > ><br>
> > <br>
> > -- <br>
> > _,,,^..^,,,_<br>
> > best, Eliot<br>
> > -------------- next part --------------<br>
> > An HTML attachment was scrubbed...<br>
> > URL: <<a href="http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20211128/ceb22524/attachment-0001.html" rel="noreferrer" target="_blank">http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20211128/ceb22524/attachment-0001.html</a>><br>
> > <br>
> ><br>
> <br>
> <br>
<br>
</blockquote></div><br clear="all"><div><br></div>-- <br><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>