Skip to content

Commit

Permalink
fixup! worker: prevent event loop starvation through MessagePorts
Browse files Browse the repository at this point in the history
  • Loading branch information
addaleax committed Sep 7, 2019
1 parent 56d0e4a commit fab5d00
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 4 deletions.
13 changes: 9 additions & 4 deletions src/node_messaging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -604,21 +604,26 @@ void MessagePort::OnMessage() {
HandleScope handle_scope(env()->isolate());
Local<Context> context = object(env()->isolate())->CreationContext();

ssize_t processing_limit;
size_t processing_limit;
{
Mutex::ScopedLock(data_->mutex_);
processing_limit = data_->incoming_messages_.size();
processing_limit = std::max(data_->incoming_messages_.size(),
static_cast<size_t>(1000));
}

// data_ can only ever be modified by the owner thread, so no need to lock.
// However, the message port may be transferred while it is processing
// messages, so we need to check that this handle still owns its `data_` field
// on every iteration.
while (data_) {
if (--processing_limit < 0) {
if (processing_limit-- == 0) {
// Prevent event loop starvation by only processing those messages without
// interruption that were already present when the OnMessage() call was
// first triggered.
// first triggered, but at least 1000 messages because otherwise the
// overhead of repeatedly triggering the uv_async_t instance becomes
// noticable, at least on Windows.
// (That might require more investigation by somebody more familiar with
// Windows.)
TriggerAsync();
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ port1.on('message', () => {

port2.postMessage(0);

// This is part of the test -- the event loop should be available and not stall
// out due to the recursive .postMessage() calls.
setTimeout(common.mustCall(), 0);

0 comments on commit fab5d00

Please sign in to comment.