Broken Promises, Exceptions might need to be Values, and Stack Traces

43 views
Skip to first unread message

Stefan Marr

unread,
Feb 27, 2017, 7:25:35 AM2/27/17
to Newspeak Programming Language
Hi:

As a simple projects to get started on SOMns, I was asking a student to finally implement errors/breaking of promises.
Just for the context, while SOMns has actors and promises, I never really implemented error handling, because, well, benchmarks don't typically use exceptions in such a way...

Unfortunately, this seems to be a bigger project than I anticipated.

I should probably also mention that my Promise class looks a little different from what I see in the Newspeak source (https://github.com/smarr/SOMns/blob/master/core-lib/Actors.som#L61 vs. https://bitbucket.org/newspeaklanguage/newspeak/src/tip/Actors.ns?at=default&fileviewer=file-view-default#Actors.ns-563).

Naming differences aside, when I originally sketched the Promise class, I wanted to offer an interface that's close to the sequential world. So, I included #ensure:, #on:do:, and the general #onError:.
However, I didn't really think about it further.

Now when implementing things, a couple of design decisions start to interact in ways that do not seem ideal.


# Exception Filtering

As I said, I wanted to minimize the difference of how broken promises are handled from how exceptions are handled in the sequential case.
This means, the #on:do: would trigger the do block only for the exception given as 'on:' parameter.
The question now is however, whether that should be influencing how other error handling callbacks are treated.
I didn't think of it before, but there are semantic differences.
Normally, all callbacks on a promise are triggered. 
But for sequential exceptions, we only trigger the first #do: that matches, and then do not continue to propagate the exception.

So, now I am questioning whether this wasn't a good idea in the first place, especially since Newspeak doesn't seem to have it.

Did you guys discuss something in that direction?

I am also wondering because you have a comment in the #when:fulfilled: method, which delegates to the #whenFulfilled:whenBroken: by passing a [:e | e signal ] block.
The comment asks whether that shouldn't be a nil block.
This makes me wonder whether you can actually have more than one set of callbacks.
It seems like signalling the exception like this, for every fulfilled callback registered, isn't a good idea.

# Exceptions need to be Values

The next thing that's problematic is that exceptions need to be values to be really useful, I think.
With this I mean that you can directly, sequentially interact with them in an #onError: handler.
However, that's highly restricting.
I can't really make all exceptions values, because then you can't reference any normal objects.

You guys don't yet have Values, right?
But perhaps you still got some thoughts on what one could do with the exception hierarchy to make this convenient.

# Exceptions and Stack Traces

The next issues is the design of exceptions, and for instance what capabilities they provide.
Classically, one would want to have access to things like stack traces. But, in a capability model, that seems to be a rather bad idea.
So, do you have a separate mirror to allow access to a stack trace associated with an exception? I haven't check for that in the code.

Any comments appreciated.

Thanks
Stefan

Ryan Macnak

unread,
Feb 27, 2017, 11:32:11 PM2/27/17
to newspeak...@googlegroups.com
Hi Stefan,

The behavior of broken promises isn't yet well thought out, so more issues than answers below:

On Mon, Feb 27, 2017 at 4:25 AM, Stefan Marr <goo...@stefan-marr.de> wrote:
Hi:

As a simple projects to get started on SOMns, I was asking a student to finally implement errors/breaking of promises.
Just for the context, while SOMns has actors and promises, I never really implemented error handling, because, well, benchmarks don't typically use exceptions in such a way...

Unfortunately, this seems to be a bigger project than I anticipated.

I should probably also mention that my Promise class looks a little different from what I see in the Newspeak source (https://github.com/smarr/SOMns/blob/master/core-lib/Actors.som#L61 vs. https://bitbucket.org/newspeaklanguage/newspeak/src/tip/Actors.ns?at=default&fileviewer=file-view-default#Actors.ns-563).

Naming differences aside, when I originally sketched the Promise class, I wanted to offer an interface that's close to the sequential world. So, I included #ensure:, #on:do:, and the general #onError:.
However, I didn't really think about it further.

Now when implementing things, a couple of design decisions start to interact in ways that do not seem ideal.


# Exception Filtering

As I said, I wanted to minimize the difference of how broken promises are handled from how exceptions are handled in the sequential case.
This means, the #on:do: would trigger the do block only for the exception given as 'on:' parameter.
The question now is however, whether that should be influencing how other error handling callbacks are treated.
I didn't think of it before, but there are semantic differences.
Normally, all callbacks on a promise are triggered. 
But for sequential exceptions, we only trigger the first #do: that matches, and then do not continue to propagate the exception.

Well, sequentially it may be propagated with #pass.

So, now I am questioning whether this wasn't a good idea in the first place, especially since Newspeak doesn't seem to have it.

My instinct is to say all handlers are activated. In particular, the handlers might all be from different actors and activating only one would undermine their independence. It would mean that control splits for async exceptions but not sync exceptions, but that's already true of async returns versus sync returns.

Did you guys discuss something in that direction?

I am also wondering because you have a comment in the #when:fulfilled: method, which delegates to the #whenFulfilled:whenBroken: by passing a [:e | e signal ] block.
The comment asks whether that shouldn't be a nil block.
This makes me wonder whether you can actually have more than one set of callbacks.
It seems like signalling the exception like this, for every fulfilled callback registered, isn't a good idea.

This path hasn't been tested much. The implementation is broken here. It lets exceptions flow as near references across actors, and that resignaling overwrites the link to the signaling activation. Though it's not clear exactly what it should do.
 
# Exceptions need to be Values

The next thing that's problematic is that exceptions need to be values to be really useful, I think.
With this I mean that you can directly, sequentially interact with them in an #onError: handler.

Right, sending more eventual sends to an actor you just got a broken promise from could easily lead to more broken promises instead of an understanding why the original operation failed.
 
However, that's highly restricting.
I can't really make all exceptions values, because then you can't reference any normal objects.

And Smalltalk-style exceptions are interesting precisely because they aren't Values: every exception has a reference to the activation that signaled it. There's certainly a tension between preserving this property and avoiding very chatty async exception handlers.

You guys don't yet have Values, right?

The current implementation knows that literals and top-level classes are Values, but doesn't allow for user-defined Values.
 
But perhaps you still got some thoughts on what one could do with the exception hierarchy to make this convenient.

# Exceptions and Stack Traces

The next issues is the design of exceptions, and for instance what capabilities they provide.
Classically, one would want to have access to things like stack traces.

I want to emphasize that Smalltalk-style exceptions reference a live stack, not a mere stack trace.

But, in a capability model, that seems to be a rather bad idea.
So, do you have a separate mirror to allow access to a stack trace associated with an exception? I haven't check for that in the code.

Not yet. In Newspeak-on-Squeak, the signaling activation is publicly available from the exception because we're still using the Smalltalk implementation of Exception. In Primordial Soup, the activation is properly hidden, but there's also no debugger yet. I expect to eventually add mirror support (1) to access the signaling activation of an exception, (2) to intercept the signaling during eval or perform, and (3) to register an actor-scoped unhandled exception callback.

Ryan

Reply all
Reply to author
Forward
0 new messages