Created
October 12, 2012 15:17
-
-
Save apaprocki/3879707 to your computer and use it in GitHub Desktop.
V8::TerminateException with TryCatch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <pthread.h> | |
#include <unistd.h> | |
#include <iostream> | |
#include <v8.h> | |
using namespace v8; | |
static void *run(void *ptr) { | |
// Terminate the execution on the main thread in one second. | |
sleep(1); | |
V8::TerminateExecution(); | |
pthread_exit(0); | |
} | |
int main(void) { | |
pthread_t thread; | |
HandleScope scope; | |
Persistent<Context> context = Context::New(); | |
Context::Scope contextscope(context); | |
Local<String> source = String::New("while(true) {}"); | |
Local<Script> script = Script::Compile(source); | |
// Catch any exceptions, kick off thread, and execute infinite loop. | |
TryCatch trycatch; | |
pthread_create(&thread, 0, &run, 0); | |
Local<Value> result = script->Run(); | |
// Result will be that execution is *not* terminating and an | |
// exception has been caught. | |
std::cout << "IsExecutionTerminating " | |
<< V8::IsExecutionTerminating() << std::endl; | |
std::cout << "TryCatch.HasCaught() " | |
<< trycatch.HasCaught() << std::endl; | |
if (trycatch.HasCaught()) { | |
// Inspection of the exception is that it is simply null. | |
// There is no real way to tell that execution terminated, | |
// unless you implicitly check for null and empty message/stack?? | |
std::cout << "TryCatch.Exception->IsNull() " << | |
trycatch.Exception()->IsNull() << std::endl; | |
std::cout << "TryCatch.Message.IsEmpty() " << | |
trycatch.Message().IsEmpty() << std::endl; | |
std::cout << "TryCatch.StackTrace.IsEmpty() " << | |
trycatch.StackTrace().IsEmpty() << std::endl; | |
} | |
context.Dispose(); | |
pthread_join(thread, 0); | |
return 0; | |
} | |
// Output: | |
// IsExecutionTerminating 0 | |
// TryCatch.HasCaught() 1 | |
// TryCatch.Exception->IsNull() 1 | |
// TryCatch.Message.IsEmpty() 1 | |
// TryCatch.StackTrace.IsEmpty() 1 |
I don't think you can overwrite exception with your own or stop unwinding the stack while there are still JS frames alive... at least this does not seem like an intended variant of usage for this API at the moment.
You should file a bug against V8 and describe your pattern to V8 team so that they might decide to extend functionality to accomodate it.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ok. When this happens, and there are JS frames still on the stack, are you allowed to
ThrowException
if you desire to actually translate it into an exception that can be caught? Or can you only do that after the last JS frame has handled the termination andIsExecutionTerminating
returnsfalse
? Based on the language in the header, I'm guessing you can't do this:When I try the above, an exception is thrown, but the exception value
IsUndefined()
. (This behavior seems strange, but I guess is acceptable if it is undefined behavior to callThrowException
whenIsExecutionTerminating
.)I'm trying to do all this because I want
vm.runInThisContext(script, name, timeout)
to be able to throw to the caller if the timeout expires. But because there are still Node JS frames in the stack when the script is terminated, there is no way to recover at therunInThisContext
boundary and throw something at that exact point.I guess I'm looking for some kind of checkpoint concept, where
TerminateExecution
will only terminate up until the first checkpoint it finds and then resumes normally, only terminating fully up the stack if no such checkpoint exists.