1 #include <node.h>
2 #include <v8.h>
3 #include <thread> // NOLINT(build/c++11)
4
5 using node::Environment;
6 using v8::Context;
7 using v8::FunctionCallbackInfo;
8 using v8::HandleScope;
9 using v8::Isolate;
10 using v8::Local;
11 using v8::Maybe;
12 using v8::Object;
13 using v8::String;
14 using v8::Value;
15
16 static std::thread interrupt_thread;
17
ScheduleInterrupt(const FunctionCallbackInfo<Value>& args)18 void ScheduleInterrupt(const FunctionCallbackInfo<Value>& args) {
19 Isolate* isolate = args.GetIsolate();
20 HandleScope handle_scope(isolate);
21 Environment* env = node::GetCurrentEnvironment(isolate->GetCurrentContext());
22
23 interrupt_thread = std::thread([=]() {
24 std::this_thread::sleep_for(std::chrono::seconds(1));
25 node::RequestInterrupt(
26 env,
27 [](void* data) {
28 // Interrupt is called from JS thread.
29 interrupt_thread.join();
30 exit(0);
31 },
32 nullptr);
33 });
34 }
35
ScheduleInterruptWithJS(const FunctionCallbackInfo<Value>& args)36 void ScheduleInterruptWithJS(const FunctionCallbackInfo<Value>& args) {
37 Isolate* isolate = args.GetIsolate();
38 HandleScope handle_scope(isolate);
39 Environment* env = node::GetCurrentEnvironment(isolate->GetCurrentContext());
40
41 interrupt_thread = std::thread([=]() {
42 std::this_thread::sleep_for(std::chrono::seconds(1));
43 node::RequestInterrupt(
44 env,
45 [](void* data) {
46 // Interrupt is called from JS thread.
47 interrupt_thread.join();
48 Isolate* isolate = static_cast<Isolate*>(data);
49 HandleScope handle_scope(isolate);
50 Local<Context> ctx = isolate->GetCurrentContext();
51 Local<String> str =
52 String::NewFromUtf8(isolate, "interrupt").ToLocalChecked();
53 // Calling into JS should abort immediately.
54 Maybe<bool> result = ctx->Global()->Set(ctx, str, str);
55 // Should not reach here.
56 if (!result.IsNothing()) {
57 // Called into JavaScript.
58 exit(2);
59 }
60 // Maybe exception thrown.
61 exit(1);
62 },
63 isolate);
64 });
65 }
66
init(Local<Object> exports)67 void init(Local<Object> exports) {
68 NODE_SET_METHOD(exports, "scheduleInterrupt", ScheduleInterrupt);
69 NODE_SET_METHOD(exports, "ScheduleInterruptWithJS", ScheduleInterruptWithJS);
70 }
71
72 NODE_MODULE(NODE_GYP_MODULE_NAME, init)
73