Hi,

I found that at the only place Isolate::TerminateExecution is called
<https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/workers/worker_thread.cc?type=cs&sq=package:chromium&g=0&l=415>
from
blink, V8 is not even running. That would mean that we don't have to worry
about any of this?

Cheers,

Yang

On Wed, Nov 14, 2018 at 10:00 AM Yang Guo <yang...@chromium.org> wrote:

> I filed a bug for the slightly counter-intuitive behavior I mentioned:
> https://bugs.chromium.org/p/v8/issues/detail?id=8455
>
> Cheers,
>
> Yang
>
> On Wed, Nov 14, 2018 at 9:01 AM Yang Guo <yang...@chromium.org> wrote:
>
>> When you terminate execution in V8, we abort execution until the
>> bottom-most call into V8. If you have re-entries into V8, V8 always returns
>> empty results until the bottom-most call into V8. On the Blink side on the
>> stack of the re-entries, you can try to call into V8 before returning, but
>> that will simply return empty results. v8::TryCatch scopes along the way
>> will return true for v8::TryCatch::HasCaught and
>> v8::TryCatch::HasTerminated. Isolate::IsExecutionTerminating returns true.
>>
>> As soon as we reach the bottom-most call, we return with an empty value
>> as well. The v8::TryCatch scope around that will return true for
>> v8::TryCatch::HasCaught and v8::TryCatch::HasTerminated, but
>> Isolate::IsExecutionTerminating will return false (even if you are still
>> inside this outer-most v8::TryCatch scope), because you can safely call
>> into V8 again, from here on. I actually find this a bit counter-intuitive,
>> and it might be better to have Isolate::IsExecutionTerminating return true,
>> until we leave the outer-most v8::TryCatch. Though implementing that seems
>> a bit annoying.
>>
>> So what you are observing is that you have a non-reentry call to execute
>> the worker. That terminates, and you then have another non-reentry call.
>> That is working as intended though. Once you have left V8 through
>> termination across all re-entries, the isolate is good to be re-used again.
>> I think the correct way to fix your issue is to, at non-reentry calls, 
>> *always
>> check for v8::TryCatch::HasTerminated, and use that to guide the following
>> control flow*.
>>
>> To answer your questions:
>>
>>> 1. What happens if the isolate is forcibly terminated (from another
>>> thread) while running a script? Will an exception be thrown? Is a
>>> v8::TryCatch catches the exception?
>>
>> Internally we throw a special exception that cannot be caught by
>> javascript. This exception causes execution to abort until we arrive at the
>> first (non-reentry) call into V8.
>>
>> 2. What happens if we try to run a script when the isolate has already
>>> been terminated?
>>
>> If you completely exited V8 back to the first non-reentry call, you can
>> safely use the isolate again.
>>
>> 3. What happens if v8 calls blink code, the isolate is forcibly
>>> terminated and then the control is back to v8?
>>
>> The termination exception is propagated back to V8, causes the current
>> execution to abort, so that we return an empty value to blink as soon as
>> possible. If this blink frame is called from V8, then calling into V8 will
>> only result in empty values.
>>
>> Cheers,
>>
>> Yang
>>
>>
>>
>> On Sat, Nov 10, 2018 at 12:15 AM Adam Klein <ad...@chromium.org> wrote:
>>
>>> On Thu, Nov 8, 2018 at 8:21 PM Yutaka Hirano <yhir...@chromium.org>
>>> wrote:
>>>
>>>> > As to the problem itself, I have a clarifying questions: doesn't
>>>> Blink already have some choke point to determine whether it's "ok to call
>>>> script now"? If so that'd be a more natural place to add this handling than
>>>> TryCatch.
>>>>
>>>> No, there isn't such a point. To make matters worse, some call-sites
>>>> don't check errors because they don't care.
>>>>
>>>> Sorry for the ignorance but I would like to know V8's policy on
>>>> termination.
>>>>
>>>> 1. What happens if the isolate is forcibly terminated (from another
>>>> thread) while running a script? Will an exception be thrown? Is a
>>>> v8::TryCatch catches the exception?
>>>> 2. What happens if we try to run a script when the isolate has already
>>>> been terminated?
>>>> 3. What happens if v8 calls blink code, the isolate is forcibly
>>>> terminated and then the control is back to v8?
>>>>
>>>>
>>> I'm not intimately familiar with the details here. Yang or Toon, perhaps
>>> you have more insight?
>>>
>>>
>>>>
>>>>
>>>> On Fri, Nov 9, 2018 at 5:30 AM Adam Klein <ad...@chromium.org> wrote:
>>>>
>>>>> Adding a couple more V8 folks who may have thoughts.
>>>>>
>>>>> On Thu, Nov 8, 2018 at 1:59 AM Kentaro Hara <hara...@chromium.org>
>>>>> wrote:
>>>>>
>>>>>> On Thu, Nov 8, 2018 at 1:10 AM Yuki Shiino <yukishi...@chromium.org>
>>>>>> wrote:
>>>>>>
>>>>>>> +adamk, cbruni to get more attention from V8 team.  This needs V8
>>>>>>> team's support.
>>>>>>>
>>>>>>> Actually, I intended haraken's (a3) at my proposal (a), but I'm
>>>>>>> afraid that changing an existing API HasCaught() would break backward
>>>>>>> compatibility.  So, I'm also proposing to add a new V8 API like
>>>>>>> v8::TryCatch::HasPendingException or 
>>>>>>> v8::TryCatch::HasCaughtOrTerminated or
>>>>>>> whatever we call it.
>>>>>>>
>>>>>>> By the way, the example code is just an example.  Usually we don't
>>>>>>> have two TryCatch blocks next to each other, and Blink is rethrowing the
>>>>>>> exception in most cases.  I just forgot to write rethrow in the example.
>>>>>>> That's not a point.  Let me revise the example.
>>>>>>>
>>>>>>> Main thread:
>>>>>>>     v8::Isolate* worker_isolate = ...;
>>>>>>>     worker_isolate->TerminateExecution();  // Terminates the worker
>>>>>>> isolate.
>>>>>>>
>>>>>>> Worker thread (worker isolate):
>>>>>>>     Foo();  // The v8::Isolate terminates during execution of Foo.
>>>>>>>     Bar();
>>>>>>>
>>>>>>> where Foo and Bar are the followings.
>>>>>>>
>>>>>>>     void Foo() {
>>>>>>>       v8::TryCatch try_catch1(isolate);
>>>>>>>       // Call V8 APIs.  The v8::Isolate gets terminated at this
>>>>>>> point.
>>>>>>>       if (try_catch1.HasCaught()) {  // => true due to the
>>>>>>> termination exception.
>>>>>>>         // Rethrow or report the error to global error handlers.
>>>>>>>         return;
>>>>>>>       }
>>>>>>>     }
>>>>>>>
>>>>>>>     void Bar() {
>>>>>>>       v8::TryCatch try_catch2(isolate);
>>>>>>>       // Call V8 APIs.  V8 APIs fail because the isolate is
>>>>>>> terminating.
>>>>>>>       if (try_catch2.HasCaught()) {  // => false because no new
>>>>>>> exception is thrown inside |try_catch2| scope.
>>>>>>>         // Rethrow or report the error to global error handlers.
>>>>>>>         return;
>>>>>>>       }
>>>>>>>       // Blink reaches here.  :(
>>>>>>>     }
>>>>>>>
>>>>>>
>>>>>> Hmm, I'm a bit confused.
>>>>>>
>>>>>> If Foo() rethrows the exception, why does the worker thread continue
>>>>>> execution and call Bar()? That will cause a problem even when the worker 
>>>>>> is
>>>>>> not terminated (because the worker continues execution ignoring the 
>>>>>> thrown
>>>>>> exception)...?
>>>>>>
>>>>>> Also I might want to understand how widely the problem is happening.
>>>>>> First of all, it is not realistic to handle worker's sudden termination 
>>>>>> in
>>>>>> 100% cases (unless we add checks to all V8 API calls in the Blink code
>>>>>> base). So the best thing we can do is to insert the termination check to
>>>>>> places that may call scripts (e.g., V8ScriptRunner, EventListener, 
>>>>>> Promise
>>>>>> resolve / reject etc) and reduce the crash rate. We could introduce
>>>>>> HasCaughtOrTerminated() if it helps to reduce the crash rate, but I want 
>>>>>> to
>>>>>> make sure that assumption is correct. My intuition is that it will be 
>>>>>> more
>>>>>> useful to identify places that may call scripts often and insert the
>>>>>> termination checks if missing.
>>>>>>
>>>>>
>>>>> I'd similarly like to understand how much this happens in practice.
>>>>>
>>>>>
>>>>>> A proposed solution looks like the following.
>>>>>>>
>>>>>>>     v8::TryCatch try_catch(isolate);
>>>>>>>     // ...
>>>>>>>     if (try_catch.*HasCaughtOrTerminated*()) {
>>>>>>>       v8::Local<v8::Exception> exception = try_catch.
>>>>>>> *CaughtExceptionOrTerminationException*();
>>>>>>>       // Do a job with |exception|.
>>>>>>>       return;
>>>>>>>     }
>>>>>>>
>>>>>>> where HasCaughtOrTerminated returns true when the isolate is
>>>>>>> terminating even if no exception is thrown inside the TryCatch scope, 
>>>>>>> and
>>>>>>> CaughtExceptionOrTerminationException returns a thrown exception if an
>>>>>>> exception is thrown inside the TryCatch scope or the termination 
>>>>>>> exception
>>>>>>> if the isolate is terminating.
>>>>>>>
>>>>>>
>>>>> As to the problem itself, I have a clarifying questions: doesn't Blink
>>>>> already have some choke point to determine whether it's "ok to call script
>>>>> now"? If so that'd be a more natural place to add this handling than
>>>>> TryCatch.
>>>>>
>>>>> - Adam
>>>>>
>>>>>
>>>>>> Cheers,
>>>>>>> Yuki Shiino
>>>>>>>
>>>>>>>
>>>>>>> 2018年11月8日(木) 17:38 Kentaro Hara <hara...@chromium.org>:
>>>>>>>
>>>>>>>> Thanks, I got it :)
>>>>>>>>
>>>>>>>> My proposal would be:
>>>>>>>>
>>>>>>>> (a3) Make HasCaught() return true when the isolate is terminated.
>>>>>>>>
>>>>>>>> I'm not sure if (a) or (a2) is a good idea because the fact that we
>>>>>>>> didn't call ReThrow() means that we (intentionally) suppressed the
>>>>>>>> exception. Thoughts?
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On Wed, Nov 7, 2018 at 9:51 PM Yuki Shiino <yukishi...@chromium.org>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>> Are you assuming that the worker is terminated while it's calling
>>>>>>>>>> DoSomethingElseWithV8()? If yes, why does HasCaught() not return 
>>>>>>>>>> true? If
>>>>>>>>>> no, what's a problem of continuing execution?
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> No, the worker is terminated while DoSomethingWithV8 (without
>>>>>>>>> "Else"), and Blink continues running more V8 code at
>>>>>>>>> DoSomethingElseWithV8.  Two pieces of code run consecutively.
>>>>>>>>>
>>>>>>>>> Worker thread (worker isolate):
>>>>>>>>>     {
>>>>>>>>>       v8::TryCatch try_catch(isolate);
>>>>>>>>>       DoSomethingWithV8();  // The Isolate terminates here.
>>>>>>>>>       if (try_catch.HasCaught()) {  // => true due to termination
>>>>>>>>>         // Handle error or termination.
>>>>>>>>>         return;
>>>>>>>>>       }
>>>>>>>>>     }
>>>>>>>>>     {
>>>>>>>>>       v8::TryCatch try_catch(isolate);
>>>>>>>>>       DoSomethingElseWithV8();  // V8 APIs fail because the
>>>>>>>>> Isolate is terminating.
>>>>>>>>>       if (try_catch.HasCaught()) {  // => false because no new
>>>>>>>>> exception is thrown inside the v8::TryCatch.
>>>>>>>>>         return;  // Blink doesn't reach here.
>>>>>>>>>       }
>>>>>>>>>       // Blink reach here instead.  :(
>>>>>>>>>     }
>>>>>>>>>
>>>>>>>>> IIUC, the second try_catch.HasCaught() doesn't return true because
>>>>>>>>> there is no new exception thrown inside the v8::TryCatch scope, 
>>>>>>>>> although V8
>>>>>>>>> APIs fail inside DoSomethingElseWithV8 due to a pending termination
>>>>>>>>> exception.
>>>>>>>>>
>>>>>>>>> Cheers,
>>>>>>>>> Yuki Shiino
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> 2018年11月8日(木) 3:18 Kentaro Hara <hara...@chromium.org>:
>>>>>>>>>
>>>>>>>>>> Sorry, I'm not sure if I understand your example...
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Wed, Nov 7, 2018 at 2:21 AM Yutaka Hirano <
>>>>>>>>>> yhir...@chromium.org> wrote:
>>>>>>>>>>
>>>>>>>>>>> +ricea@
>>>>>>>>>>>
>>>>>>>>>>> On Wed, Nov 7, 2018 at 6:44 PM Yuki Shiino <
>>>>>>>>>>> yukishi...@chromium.org> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> Hi V8-team and platform-architecture-dev,
>>>>>>>>>>>>
>>>>>>>>>>>> TL;DR: We'd like to extend v8::TryCatch APIs a little.
>>>>>>>>>>>>
>>>>>>>>>>>> We're having an issue how to handle worker termination, i.e.
>>>>>>>>>>>> v8::Isolate termination.  Roughly speaking, the situation is like 
>>>>>>>>>>>> below.
>>>>>>>>>>>>
>>>>>>>>>>>> Main thread:
>>>>>>>>>>>>     v8::Isolate* worker_isolate = ...;
>>>>>>>>>>>>     worker_isolate->TerminateExecution();  // Terminates the
>>>>>>>>>>>> worker isolate.
>>>>>>>>>>>>
>>>>>>>>>>>> Worker thread (worker isolate):
>>>>>>>>>>>>     v8::TryCatch try_catch(isolate);
>>>>>>>>>>>>     DoSomethingWithV8();  // The Isolate terminates here.
>>>>>>>>>>>>     if (try_catch.HasCaught()) {  // => true due to termination
>>>>>>>>>>>>       // Handle error or termination.
>>>>>>>>>>>>       return;
>>>>>>>>>>>>     }
>>>>>>>>>>>>
>>>>>>>>>>>> No problem so far.  Worker thread MUST NOT run any V8 code no
>>>>>>>>>>>> longer because the Isolate is terminating.  However, Blink is not 
>>>>>>>>>>>> perfect,
>>>>>>>>>>>> and it's pretty tough for Blink to stop everything with 100% 
>>>>>>>>>>>> correctness.
>>>>>>>>>>>> Occasionally (or rarely) Blink continues running more V8 code like 
>>>>>>>>>>>> below.
>>>>>>>>>>>>
>>>>>>>>>>>> Worker thread (worker isolate):
>>>>>>>>>>>>     v8::TryCatch try_catch(isolate);
>>>>>>>>>>>>     DoSomethingElseWithV8();
>>>>>>>>>>>>     if (try_catch.HasCaught()) {  // => false because no new
>>>>>>>>>>>> exception is thrown inside the v8::TryCatch.
>>>>>>>>>>>>       return;  // Blink doesn't reach here.
>>>>>>>>>>>>     }
>>>>>>>>>>>>     // Blink reach here instead.  :(
>>>>>>>>>>>>
>>>>>>>>>>>> If v8::TryCatch::HasCaught() returned true, Blink would be able
>>>>>>>>>>>> to handle it as error and Blink would work much better than now 
>>>>>>>>>>>> (Blink is
>>>>>>>>>>>> now crashing).
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>> Are you assuming that the worker is terminated while it's calling
>>>>>>>>>> DoSomethingElseWithV8()? If yes, why does HasCaught() not return 
>>>>>>>>>> true? If
>>>>>>>>>> no, what's a problem of continuing execution?
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>>> So, proposals here are something like below (not yet so
>>>>>>>>>>>> concrete).
>>>>>>>>>>>>
>>>>>>>>>>>> a) Make v8::TryCatch::HasCaught() return true if there already
>>>>>>>>>>>> exists a pending exception.  (Maybe this is no good.)
>>>>>>>>>>>> b) Make a new API like v8::TryCatch::HasPendingException() and
>>>>>>>>>>>> make it return true.  Blink rewrites all HasCaught() to the new 
>>>>>>>>>>>> one.
>>>>>>>>>>>>
>>>>>>>>>>>> Similarly,
>>>>>>>>>>>>
>>>>>>>>>>>> a2) Make v8::TryCatch::Exception() return a pending exception
>>>>>>>>>>>> if there already exists.
>>>>>>>>>>>> b2) Make a new API like v8::TryCatch::PendingException() and
>>>>>>>>>>>> make it return a thrown exception or pending exception in the 
>>>>>>>>>>>> isolate if
>>>>>>>>>>>> any.  Blink rewrites all Exception() to the new one.
>>>>>>>>>>>>
>>>>>>>>>>>> What do you think of the issue and proposals?
>>>>>>>>>>>>
>>>>>>>>>>>> Cheers,
>>>>>>>>>>>> Yuki Shiino
>>>>>>>>>>>>
>>>>>>>>>>>> --
>>>>>>>>>>> You received this message because you are subscribed to the
>>>>>>>>>>> Google Groups "platform-architecture-dev" group.
>>>>>>>>>>> To unsubscribe from this group and stop receiving emails from
>>>>>>>>>>> it, send an email to
>>>>>>>>>>> platform-architecture-dev+unsubscr...@chromium.org.
>>>>>>>>>>> To post to this group, send email to
>>>>>>>>>>> platform-architecture-...@chromium.org.
>>>>>>>>>>> To view this discussion on the web visit
>>>>>>>>>>> https://groups.google.com/a/chromium.org/d/msgid/platform-architecture-dev/CABihn6ER8q9QABC3ROCSkm6V4w%2BDb0xEqRvjgzwBpMG9DmiG1Q%40mail.gmail.com
>>>>>>>>>>> <https://groups.google.com/a/chromium.org/d/msgid/platform-architecture-dev/CABihn6ER8q9QABC3ROCSkm6V4w%2BDb0xEqRvjgzwBpMG9DmiG1Q%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>>>>>>>>>> .
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> --
>>>>>>>>>> Kentaro Hara, Tokyo, Japan
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>> --
>>>>>>>> Kentaro Hara, Tokyo, Japan
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>> --
>>>>>> Kentaro Hara, Tokyo, Japan
>>>>>>
>>>>>> --
>>>>>> You received this message because you are subscribed to the Google
>>>>>> Groups "platform-architecture-dev" group.
>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>> send an email to platform-architecture-dev+unsubscr...@chromium.org.
>>>>>> To post to this group, send email to
>>>>>> platform-architecture-...@chromium.org.
>>>>>> To view this discussion on the web visit
>>>>>> https://groups.google.com/a/chromium.org/d/msgid/platform-architecture-dev/CABg10jx51JXHEt0H9z%3DzT%3D0GnhDf79QjhGtVxRc%3Dy-RXjHXUyw%40mail.gmail.com
>>>>>> <https://groups.google.com/a/chromium.org/d/msgid/platform-architecture-dev/CABg10jx51JXHEt0H9z%3DzT%3D0GnhDf79QjhGtVxRc%3Dy-RXjHXUyw%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>>>>> .
>>>>>>
>>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "platform-architecture-dev" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to platform-architecture-dev+unsubscr...@chromium.org.
>>>> To post to this group, send email to
>>>> platform-architecture-...@chromium.org.
>>>> To view this discussion on the web visit
>>>> https://groups.google.com/a/chromium.org/d/msgid/platform-architecture-dev/CABihn6GKuTUs5UfpbQ6RwXq%3DWw0dDUJkq2JLzadnesfjLG%3DStg%40mail.gmail.com
>>>> <https://groups.google.com/a/chromium.org/d/msgid/platform-architecture-dev/CABihn6GKuTUs5UfpbQ6RwXq%3DWw0dDUJkq2JLzadnesfjLG%3DStg%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "platform-architecture-dev" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to platform-architecture-dev+unsubscr...@chromium.org.
>>> To post to this group, send email to
>>> platform-architecture-...@chromium.org.
>>> To view this discussion on the web visit
>>> https://groups.google.com/a/chromium.org/d/msgid/platform-architecture-dev/CAEvLGcKKKdZ4-Svz7NmXdzSaL9ryQz4cPEqhTfmWEURzwTdMqQ%40mail.gmail.com
>>> <https://groups.google.com/a/chromium.org/d/msgid/platform-architecture-dev/CAEvLGcKKKdZ4-Svz7NmXdzSaL9ryQz4cPEqhTfmWEURzwTdMqQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>>

-- 
-- 
v8-users mailing list
v8-users@googlegroups.com
http://groups.google.com/group/v8-users
--- 
You received this message because you are subscribed to the Google Groups 
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to