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

Eliot Miranda eliot.miranda at gmail.com
Wed Dec 15 19:10:49 UTC 2021

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
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
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
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
run unwinds twice.

On Tue, Dec 14, 2021 at 5:36 PM Eliot Miranda <eliot.miranda at gmail.com>

> 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