Skip to content

Commit c582cc6

Browse files
daeyeonhs0225
authored andcommitted
fix: fix hanging event loop on errors using message port
This resolves an issue where the loop does not exit when an error occurs in the script after the `onmessage` of message port is registered. Signed-off-by: Daeyeon Jeong <[email protected]>
1 parent 5c2e871 commit c582cc6

File tree

6 files changed

+70
-0
lines changed

6 files changed

+70
-0
lines changed

deps/node/src/env-inl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,8 @@ inline bool Environment::can_call_into_js() const {
790790
}
791791

792792
inline void Environment::set_can_call_into_js(bool can_call_into_js) {
793+
// @lwnode
794+
LWNode::SetCanCallIntoJS(can_call_into_js);
793795
can_call_into_js_ = can_call_into_js;
794796
}
795797

include/lwnode/lwnode.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ void InitMainMessagePort(v8::Local<v8::Context> context,
5252
LoopHolderUV* loop_holder,
5353
uv_loop_t* loop);
5454

55+
bool CanCallIntoJs();
56+
void SetCanCallIntoJS(bool can_call_into_js);
57+
5558
void IdleGC(v8::Isolate* isolate = nullptr);
5659
void initDebugger();
5760
bool dumpSelfMemorySnapshot();

src/lwnode/lwnode.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,17 @@ void InitMainMessagePort(Local<Context> context,
283283
lwContext->SetAlignedPointerInEmbedderData(kLoopHolder, loop_holder);
284284
}
285285

286+
// FIXME: Move to a better place (e.g. context or isolate)
287+
thread_local static bool s_can_call_into_js{true};
288+
289+
bool CanCallIntoJs() {
290+
return s_can_call_into_js;
291+
}
292+
293+
void SetCanCallIntoJS(bool can_call_into_js) {
294+
s_can_call_into_js = can_call_into_js;
295+
}
296+
286297
void InitializeProcessMethods(Local<Object> target, Local<Context> context) {
287298
auto esContext = CVAL(*context)->context()->get();
288299
auto esTarget = CVAL(*target)->value()->asObject();

src/lwnode/nd-mod-message-port.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,12 @@ class MessagePortWrap : public BaseObject {
222222
return;
223223
}
224224

225+
#if defined(LWNODE)
226+
if (LWNode::CanCallIntoJs() == false) {
227+
return;
228+
}
229+
#endif
230+
225231
ExecResult result =
226232
Eval::execute(context, [this, event](ExecutionStateRef* state) {
227233
ObjectRef* event_object = InstantiateMessageEvent(state, event);

test/embedding/embedtest.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,38 @@ TEST0(Embedtest, RestartAfterStop) {
142142
std::cout << count << " /Thread " << std::endl;
143143
}
144144
}
145+
146+
TEST(Embedtest, MessagePortErrorAfterRegisterOnMessage, 5000) {
147+
auto runtime = std::make_shared<lwnode::Runtime>();
148+
149+
std::promise<void> promise;
150+
std::future<void> init_future = promise.get_future();
151+
const char* script = "test/embedding/test-04-message-port-error.js";
152+
std::string path = (std::filesystem::current_path() / script).string();
153+
154+
const bool post_first = true;
155+
char* args[] = {const_cast<char*>(""),
156+
const_cast<char*>(path.c_str()),
157+
const_cast<char*>(std::to_string(post_first).c_str())};
158+
159+
std::thread worker = std::thread(
160+
[&](std::promise<void>&& promise) mutable {
161+
runtime->Start(COUNT_OF(args), args, std::move(promise));
162+
},
163+
std::move(promise));
164+
165+
init_future.wait();
166+
167+
int count1 = 0;
168+
169+
auto port2 = runtime->GetPort();
170+
171+
port2->OnMessage([&](const MessageEvent* event) {
172+
std::cout << event->data() << std::endl;
173+
count1++;
174+
});
175+
port2->PostMessage(MessageEvent::New("ping"));
176+
177+
// This test should not exit due to timeout
178+
worker.join();
179+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const lwnode = process.lwnode;
2+
const port = process.lwnode.port;
3+
4+
lwnode.ref();
5+
6+
port.onmessage = (event) => {
7+
if (event.data == "ping") {
8+
port.postMessage("pong");
9+
lwnode.unref();
10+
}
11+
};
12+
13+
error

0 commit comments

Comments
 (0)