Uncatchable exceptions

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Uncatchable exceptions

Ehsan Akhgari
AFAIK there is some notion of uncatchable exceptions in SpiderMonkey in
case a JSNative returns false, which is used in Gecko.  Are there other
similar cases in SpiderMonkey?  There doesn't seem to be any way to
raise/detect such exceptions through the JS API.

Also, is there any notion of terminating the execution of JS through other
means?

Thanks,
--
Ehsan
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Uncatchable exceptions

Bobby Holley-2
Historically, returning false without setting a pending exception was
considered uncatchable, and was the way to signal OOM, terminate slow
scripts, etc. The idea is that callers are always supposed to propagate
|false| return values, and if there wasn't any associated exception state,
there was nothing they could do but propagate it upward.

Recently, OOMs were converted to use some kind of pseudo-exception on the
JSContext. There is some related discussion at [1]. I think that the slow
script dialog / interrupt callback mechanism still uses plain |return
false|, but I haven't checked.

[1]
https://groups.google.com/d/msg/mozilla.dev.tech.js-engine.internals/6icIj0U0wDo/T70QBToLBwAJ

On Mon, May 2, 2016 at 2:15 PM, Ehsan Akhgari <[hidden email]>
wrote:

> AFAIK there is some notion of uncatchable exceptions in SpiderMonkey in
> case a JSNative returns false, which is used in Gecko.  Are there other
> similar cases in SpiderMonkey?  There doesn't seem to be any way to
> raise/detect such exceptions through the JS API.
>
> Also, is there any notion of terminating the execution of JS through other
> means?
>
> Thanks,
> --
> Ehsan
> _______________________________________________
> dev-tech-js-engine mailing list
> [hidden email]
> https://lists.mozilla.org/listinfo/dev-tech-js-engine
>
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Uncatchable exceptions

Ehsan Akhgari
I guess I may have not been clear enough in my original post, let me try
again!

The V8 API exposes the notion of "terminating exceptions" which are
exceptions that terminate the execution of JS but are not catchable *in*
JS.  I'll call these "uncatchable exceptions".

SpiderMonkey has the exact same notion internally.  I'd like to find a
way to implement the corresponding V8 APIs, which will require exposing
some kind of JS API, like JS_IsUncatchableExceptionPending(JSContext*).

I'm trying to figure out how to implement this function.  AFAICT the
implementation is roughly as follows:

bool JS_IsUncatchableExceptionPending(JSContext* cx) {
  return cx->didSomeJSNativeReturnFalse() ||
         cx->isThrowingOutOfMemory();
}

It is the didSomeJSNativeReturnFalse() that I don't know how to
implement.  As far as I can understand stuff that happens in js::Call()
et al, there isn't even a flag indicating such case. :(  It seems like
all that happens here is we return false and pass the ball to the
caller, which itself returns false and so on.

Can someone please help with how I can extract this information from
SpiderMonkey()?

Thanks,
Ehsan

On 2016-05-02 5:46 PM, Bobby Holley wrote:

> Historically, returning false without setting a pending exception was
> considered uncatchable, and was the way to signal OOM, terminate slow
> scripts, etc. The idea is that callers are always supposed to propagate
> |false| return values, and if there wasn't any associated exception
> state, there was nothing they could do but propagate it upward.
>
> Recently, OOMs were converted to use some kind of pseudo-exception on
> the JSContext. There is some related discussion at [1]. I think that the
> slow script dialog / interrupt callback mechanism still uses plain
> |return false|, but I haven't checked.
>
> [1]
> https://groups.google.com/d/msg/mozilla.dev.tech.js-engine.internals/6icIj0U0wDo/T70QBToLBwAJ
>
> On Mon, May 2, 2016 at 2:15 PM, Ehsan Akhgari <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     AFAIK there is some notion of uncatchable exceptions in SpiderMonkey in
>     case a JSNative returns false, which is used in Gecko.  Are there other
>     similar cases in SpiderMonkey?  There doesn't seem to be any way to
>     raise/detect such exceptions through the JS API.
>
>     Also, is there any notion of terminating the execution of JS through
>     other
>     means?
>
>     Thanks,
>     --
>     Ehsan
>     _______________________________________________
>     dev-tech-js-engine mailing list
>     [hidden email]
>     <mailto:[hidden email]>
>     https://lists.mozilla.org/listinfo/dev-tech-js-engine
>
>

_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Uncatchable exceptions

Boris Zbarsky
In reply to this post by Bobby Holley-2
On 5/2/16 9:13 PM, Ehsan Akhgari wrote:

> I'm trying to figure out how to implement this function.  AFAICT the
> implementation is roughly as follows:
>
> bool JS_IsUncatchableExceptionPending(JSContext* cx) {
>    return cx->didSomeJSNativeReturnFalse() ||
>           cx->isThrowingOutOfMemory();
> }
>
> It is the didSomeJSNativeReturnFalse() that I don't know how to
> implement.  As far as I can understand stuff that happens in js::Call()
> et al, there isn't even a flag indicating such case. :(  It seems like
> all that happens here is we return false and pass the ball to the
> caller, which itself returns false and so on.

That's correct.  That is exactly how things work right now.

I think there are basically two options here:

1)  We change the places that return false without setting pending
exceptions to make some explicit call to an API we add.  The problem is
finding them all.  :(  That said, it's not clear to me that SpiderMonkey
itself ever has this behavior.  Gecko does, for the slow script dialog
and worker termination, but all of that happens outside SpiderMonkey...
  Presumably you need to implement a "throw uncatchable exception" API
anyway, right?

2)  We restrict the use of JS_IsUncatchableExceptionPending to the
situation when false is known to have been returned.  In that case it
just becomes !cx->hasPendingException().

-Boris
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Uncatchable exceptions

Ehsan Akhgari
On 2016-05-02 9:47 PM, Boris Zbarsky wrote:

> On 5/2/16 9:13 PM, Ehsan Akhgari wrote:
>> I'm trying to figure out how to implement this function.  AFAICT the
>> implementation is roughly as follows:
>>
>> bool JS_IsUncatchableExceptionPending(JSContext* cx) {
>>    return cx->didSomeJSNativeReturnFalse() ||
>>           cx->isThrowingOutOfMemory();
>> }
>>
>> It is the didSomeJSNativeReturnFalse() that I don't know how to
>> implement.  As far as I can understand stuff that happens in js::Call()
>> et al, there isn't even a flag indicating such case. :(  It seems like
>> all that happens here is we return false and pass the ball to the
>> caller, which itself returns false and so on.
>
> That's correct.  That is exactly how things work right now.

Sadface.  :(

> I think there are basically two options here:
>
> 1)  We change the places that return false without setting pending
> exceptions to make some explicit call to an API we add.  The problem is
> finding them all.  :(  That said, it's not clear to me that SpiderMonkey
> itself ever has this behavior.  Gecko does, for the slow script dialog
> and worker termination, but all of that happens outside SpiderMonkey...
>  Presumably you need to implement a "throw uncatchable exception" API
> anyway, right?

Hmm, not sure why we would need to do all of this...  Now that I think
about it, I think we can have a flag that we set in
js::InternalCallOrConstruct() if that function returns false.  I _think_
that's the only place where these false return values can originate from?

> 2)  We restrict the use of JS_IsUncatchableExceptionPending to the
> situation when false is known to have been returned.  In that case it
> just becomes !cx->hasPendingException().

Wouldn't that essentially be JS_IsExceptionPending()?  The goal here is
to expose whether execution was terminated because of an exception that
is not catchable in JS.
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Uncatchable exceptions

Ehsan Akhgari
On 2016-05-02 11:07 PM, Ehsan Akhgari wrote:
> Hmm, not sure why we would need to do all of this...  Now that I think
> about it, I think we can have a flag that we set in
> js::InternalCallOrConstruct() if that function returns false.  I _think_
> that's the only place where these false return values can originate from?

And perhaps also handle isPropagatingForcedReturn() and count them as an
uncatchable exception too?

_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Uncatchable exceptions

Boris Zbarsky
In reply to this post by Boris Zbarsky
On 5/2/16 11:07 PM, Ehsan Akhgari wrote:
> Hmm, not sure why we would need to do all of this...  Now that I think
> about it, I think we can have a flag that we set in
> js::InternalCallOrConstruct() if that function returns false.  I _think_
> that's the only place where these false return values can originate from?

Hmm.  I don't think so, in general.

For example, say we have some C++ that does a JS_GetProperty on an
object.  The property has a scripted getter, that scripted getter
triggers the slow script dialog, the user opts to stop the script.
JS_GetProperty will return false with no exception pending, indicating
an uncatchable exception.

Or another example: running a toplevel script via JS_ExecuteScript never
comes through js::InternalCallOrConstruct as far as I can tell.

>> 2)  We restrict the use of JS_IsUncatchableExceptionPending to the
>> situation when false is known to have been returned.  In that case it
>> just becomes !cx->hasPendingException().
>
> Wouldn't that essentially be JS_IsExceptionPending()?

No.  The whole point is that the uncatchable exception case is currently
characterized by the following:

1)  false was returned.
2)  JS_IsExceptionPending() is _false_.

> The goal here is to expose whether execution was terminated because of an exception that
> is not catchable in JS.

Execution of which?  Are we just talking about execution of individual
functions and toplevel scripts, or do we need to worry about the
JS_GetProperty case above?

-Boris
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Uncatchable exceptions

Ehsan Akhgari
On 2016-05-02 11:58 PM, Boris Zbarsky wrote:

> On 5/2/16 11:07 PM, Ehsan Akhgari wrote:
>> Hmm, not sure why we would need to do all of this...  Now that I think
>> about it, I think we can have a flag that we set in
>> js::InternalCallOrConstruct() if that function returns false.  I _think_
>> that's the only place where these false return values can originate from?
>
> Hmm.  I don't think so, in general.
>
> For example, say we have some C++ that does a JS_GetProperty on an
> object.  The property has a scripted getter, that scripted getter
> triggers the slow script dialog, the user opts to stop the script.
> JS_GetProperty will return false with no exception pending, indicating
> an uncatchable exception.
>
> Or another example: running a toplevel script via JS_ExecuteScript never
> comes through js::InternalCallOrConstruct as far as I can tell.

Oh, right.  :(

>>> 2)  We restrict the use of JS_IsUncatchableExceptionPending to the
>>> situation when false is known to have been returned.  In that case it
>>> just becomes !cx->hasPendingException().
>>
>> Wouldn't that essentially be JS_IsExceptionPending()?
>
> No.  The whole point is that the uncatchable exception case is currently
> characterized by the following:
>
> 1)  false was returned.
> 2)  JS_IsExceptionPending() is _false_.

Oh, I see.

So, for an embedder, is it possible to implement this by recording false
return values from JS APIs that can run code and then assume an
uncatchable exception if JS_IsExceptionPending() would be false?

>> The goal here is to expose whether execution was terminated because of
>> an exception that
>> is not catchable in JS.
>
> Execution of which?  Are we just talking about execution of individual
> functions and toplevel scripts, or do we need to worry about the
> JS_GetProperty case above?

All of the above.
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine
Reply | Threaded
Open this post in threaded view
|

Re: Uncatchable exceptions

Boris Zbarsky
In reply to this post by Boris Zbarsky
On 5/3/16 12:33 AM, Ehsan Akhgari wrote:
> So, for an embedder, is it possible to implement this by recording false
> return values from JS APIs that can run code and then assume an
> uncatchable exception if JS_IsExceptionPending() would be false?

Yes.  If you control all the calls into JS_* you can do that.
Basically, store some state associated with the JSContext if false got
returned and JS_IsExceptionPending is false.  This should be doable with
some sort of RAII helper that gets the jsapi result assigned into it,
I'd thinkg.  Then clear the state if you decide to call
JS_ClearPendingException or whatever API you're implementing that clears
uncatchable exceptions.

-Boris
_______________________________________________
dev-tech-js-engine mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-js-engine