[squeak-dev] Re-signalling an already signaled exception

mail at jaromir.net mail at jaromir.net
Sat Feb 5 17:48:39 UTC 2022

Hi Chris,

On 2022-02-04T17:11:35-06:00, asqueaker at gmail.com wrote:

> Hi Jaromir,
> Here's a motivation example:
> >
> > [1/0] on: Error do: [:ex |
> >         [ex signal] on: ZeroDivide do: [Transcript show: #ZeroDivide]
> >         ]
> >
> > Would you expect this code to work and pick up the ZeroDivide handler?
> >
> ...
> > The point or a use case is to provide additional (finer, more specific)
> > handlers inside the general handler rather than wrap the general handler
> > inside more specific handlers. More specific handlers can even be inside a
> > method so the readability would not degrade.
> >
> I was able to do it by creating a new exception instance and signaling it:
>     [1/0] on: Error do: [: err |
>             [err copy signal] on: ZeroDivide do: [Transcript show:
> #ZeroDivide] ]
> I don't know about #copy, though, you might want to implement your own
> special #freshCopy that throws out the signalContext, handlerContext and
> outerContext, but the above "worked".  :)

Precisely, it crossed my mind too and yes, it has to be a "fresh" copy with blank instance variables (except messageText). A simple copy fails tests with nested outer etc...

I've checked ANSI again and they say, quote: [ messageText][...] Subsequent sends of of the message #messageText to a signaled exception generated by sending the message #signal to the receiver of this message [note: the receiver is an exception instance] will also return this value.

So what I'm actually looking for is this: (and it's equivalent to the "fresh" copy idea)

    [1/0] on: Error do: [: err |  
            [err class signal: err messageText] on: ZeroDivide do: [Transcript show: #ZeroDivide] ]

If I'm interpreting ANSI's intention correctly then we could update our #signal like this:

	"Ask ContextHandlers in the sender chain to handle this signal.  The default is to execute and return my defaultAction.
	Signaling an already signaled exception is interpreted as signaling a new exception of the same type with the same messageText"

-	signalContext ifNotNil: [^self outer].
+	signalContext ifNotNil: [^self copy signal: self messageText]. 
	signalContext := thisContext contextTag.
	^(thisContext nextHandlerContextForSignal: self) handleSignal: self

It was my idea last year to make subsequent sends of #signal to an already signaled exception equivalent to #outer and now I can see it was wrong and I'd like to really fix it this time :) All test are green, even the ones in Tests-jar.464.

Thanks, Chris, for discussing this.

Sent from Squeak Inbox Talk

More information about the Squeak-dev mailing list