[squeak-dev] Exception reraise (needs review) [was Exception reraiseFrom: (needs review)]

mail at jaromir.net mail at jaromir.net
Sat Dec 18 22:14:01 UTC 2021


Hi Eliot,

I'd like to share some observations:

(1)
> Once the exception has been copied, on:do: will run unwinds and answer the error
> as the result of the [nil new] on:...do:... expression. In doing so it will run the ensure:
> block inside Semaphore>>critical: and the semaphore will get back its one excess
> signal.

I'm not sure I understand: #on:do: will certainly run unwinds but the ensure block [self signal] inside #critical: is below on:do: (meaning deeper); so my understanding is the ensure block is run normally after on:do: returns and not as an unwind during on:do:'s return. Not that it changes anything, just either the comment is incorrect or I am :) The semaphore recharges in any case and when the exception is reraised the ensure block's 'complete' variable is already set true so it won't evaluate again as desired.

> The only safe thing to do is close the debugger, or return a value to
> the sender.  But if we close the debugger unwinds will be run and we *must not*
> run unwinds twice.

Yes, closing the debugger would execute the ensure block when unwinding; I hope I understand the terminology though: unwind is the procedure during returns when the ensure blocks on the stack are identified and executed outside "normal linear flow of the computation"; otherwise, when the ensure block is executed normally it wouldn't be called unwinding, right?

(2)
I tried debugging the motivation example:

| home error |
home := thisContext.
Semaphore forMutualExclusion critical:
    [[nil new]
        on: Error
        do: [:ex| error := ex copyForReraiseTo: home disableUnwinds: true]].
error reraise

When you step over, until #reraise and then step into #reraise and in and in again you get 'endIndex is out of bounds' error (in #postCopyFrom:to:). What's worse though is when you continue debugging (stepping) then in some cases the image irreparably crashes. I can't figure out why and can't see any pattern... Sometimes it just freezes beyond CMD+dot repair, or a grey screen appears or even some weird looking grey windows with scary titles start popping-up :) The only way to get rid of it is to kill it in the OS. The described sequence (stepOver 3 times, stepIn 3 times is just the fastest way to show the error; it can be replicated many other ways).

(3)
> Maybe adding a flag to Exception and avoiding that assert when the
> exception is "in reraise mode" is better.  I don't know.

yes, I tried; it works but the crashing while debugging was even worse...

One last question: when you copy the stack fragment, you create a simple tree with the two branches sharing the same context you call 'home'. The original branch returns to 'home' and sends #reraise and the copied stack branch is then run - my question is: Does it matter that the copied branch will eventually return to a different pc position in the 'home' method than it's original version? I guess not but I'm not sure.

Thanks for sharing this code, very interesting stuff to study!
Best,



~~~
^[^    Jaromir

Sent from Squeak Inbox Talk

On 2021-12-15T11:10:49-08:00, eliot.miranda at gmail.com wrote:

> Hi All, Hi Christoph, Levente, Jaromir, Vanessa,
> 
> find attached an improved implementation of copying the stack of an
> exception caught within a critical section stack for resignaling outside of
> a critical section.  The improvement and main issue here is avoiding
> running unwinds more than once.  Since the stack is copied, unwinds may be
> effectively run again if unwound in the copied stack. This implementation
> allows that to be avoided if desired.  Please review if you have time.
> 
> Here's the motivating example; actually an extract of the comment
> in Exception >> copyForReraiseTo:disableUnwinds:.
> 
> | home error |
> home := thisContext.
> Semaphore forMutualExclusion critical:
>     [[nil new]
>         on: Error
>         do: [:ex| error := ex copyForReraiseTo: home disableUnwinds: true]].
> error reraise
> 
> Once the exception has been copied, on:do: will run unwinds and answer the
> error
> as the result of the [nil new] on:...do:... expression. In doing so it will
> run the ensure:
> block inside Semaphore>>critical: and the semaphore will get back its one
> excess
> signal.  It is therefore essential that the copy of this unwind in the
> copied exception's
> stack is not run again, otherwise the semaphore will end up with two excess
> signals.
> This is why unwinds can be disabled in the copy.
> 
> It is important to understand why we disable unwinds.  Proceeding is clearly
> dangerous; we might re-enter code in a critical section, and do something
> untoward. The only safe thing to do is close the debugger, or return a
> value to
> the sender.  But if we close the debugger unwinds will be run and we *must
> not*
> run unwinds twice.
> 
> On Tue, Dec 14, 2021 at 5:36 PM Eliot Miranda <eliot.miranda at gmail.com>
> wrote:
> 
> > Hi All, Hi Levente, Jaromir, and Context hackers,
> >
> >     find attached a change set which supports re-raising a fatal
> > exception, caught inside a critical section, outside the critical section.
> > This is a key facility for debugging systems such as Croquet.  I expect
> > it'll also be useful in delimited continuation contexts such as Seaside.
> > The facility is closely related to Context>>copyTo: and
> > Context>>copyTo:bottomContextDo:.  The main method is
> > Exception>>copyForReraiseTo: aContext.
> >
> > This implementation is higher quality than
> > Context>>copyTo:[bottomContextDo:].  It copies the stack and it also copies
> > blocks that are created on the copied stack.  So the copied stack
> > correctly copies blocks, and hence exception handlers.
> >
> > I'm thinking of adding this to trunk.  I would like it to be reviewed
> > carefully before I do so.  Both implementation and selector names need
> > reviewing, and tests and more use cases would be nice (I have a use case in
> > Virtend/Croquet).
> >
> > Here's an example usage:
> >
> >     | sender error |
> >     sender := thisContext sender.
> >     Mutex new critical:
> >         [[nil new]
> >             on: Error
> >             do: [:ex| error := ex copyForReraiseTo: sender]].
> >     error reraiseFrom: thisContext
> >
> > A simpler usage would be
> >
> >     | home error |
> >     home := thisContext.
> >     Mutex new critical:
> >         [[nil new]
> >             on: Error
> >             do: [:ex| error := ex copyForReraiseTo: home]].
> >     error outer
> >
> > This doesn't
> > work because ProcessorScheduler>>#debugContext:title:full:contents: (et al)
> > contains
> >
> >     self assert: [thisContext hasSender: aContext]
> >
> > and hence we have to stitch the copied stack into the current stack via
> >
> >     aContext privSender: signalContext.
> >    thisContext privSender: aContext.
> >    self outer
> >
> > inside Exception>>reraiseFrom: aContext
> >
> > Maybe adding a flag to Exception and avoiding that assert when the
> > exception is "in reraise mode" is better.  I don't know.
> >
> >
> > Given that the main worker method, Context>>#copyTo:atEachStep:, is better
> > than Context>>copyTo:[bottomContextDo:]., these two could be reimplemented
> > in terms of it, e.g.:
> >
> > Context>>copyTo: aContext
> >     ^self copyTo: aContext
> >             atEachStep:
> >                 [:originalContext :copiedContext|
> >                 originalContext sender == aContext ifTrue:
> >                     [copiedContext privSender: nil]]
> >
> > Context>>copyTo: aContext bottomContextDo: aBlock
> >     ^self copyTo: aContext
> >             atEachStep:
> >                 [:originalContext :copiedContext|
> >                 originalContext sender == aContext ifTrue:
> >                     [copiedContext privSender: nil.
> >                     aBlock value: copiedContext]]
> >
> >
> > _,,,^..^,,,_
> > best, Eliot
> >
> 
> 
> -- 
> _,,,^..^,,,_
> best, Eliot
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20211215/ed08069f/attachment.html>
> -------------- next part --------------
> A non-text attachment was scrubbed...
> Name: reraise-methods.st
> Type: application/octet-stream
> Size: 5244 bytes
> Desc: not available
> URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20211215/ed08069f/attachment.obj>
> 
> 


More information about the Squeak-dev mailing list