Skip to content

Commit f100bf8

Browse files
committed
worker: handle detached MessagePort from a different context
When `worker.moveMessagePortToContext` is used, the async handle associated with the port, will be triggered more than needed (at least one more time) and with null data. That can be avoided by simply checking that the data is present and the port is not detached. Fixes: #49075 Signed-off-by: Juan José Arboleda <[email protected]>
1 parent 6432060 commit f100bf8

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

src/node_messaging.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,11 @@ void MessagePort::OnMessage(MessageProcessingMode mode) {
795795

796796
size_t processing_limit;
797797
if (mode == MessageProcessingMode::kNormalOperation) {
798+
// Maybe the async handle was triggered empty or more than needed
799+
// (called twiced on a new context).
800+
if (GetTransferMode() == TransferMode::kDisallowCloneAndTransfer || !data_)
801+
return;
802+
798803
Mutex::ScopedLock(data_->mutex_);
799804
processing_limit = std::max(data_->incoming_messages_.size(),
800805
static_cast<size_t>(1000));

test/parallel/test-worker-workerdata-messageport.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
'use strict';
22

33
require('../common');
4-
const assert = require('assert');
4+
const assert = require('node:assert');
55

66
const {
77
Worker, MessageChannel
8-
} = require('worker_threads');
8+
} = require('node:worker_threads');
99

1010
const channel = new MessageChannel();
1111
const workerData = { mesage: channel.port1 };
@@ -59,3 +59,29 @@ const meowScript = () => 'meow';
5959
'listed in transferList'
6060
});
6161
}
62+
63+
{
64+
// Should not crash when MessagePort is transferred to another context.
65+
// https://github.com/nodejs/node/issues/49075
66+
const channel = new MessageChannel();
67+
new Worker(`
68+
const { runInContext, createContext } = require('node:vm')
69+
const { workerData } = require('worker_threads');
70+
const context = createContext(Object.create(null));
71+
context.messagePort = workerData.messagePort;
72+
runInContext(
73+
\`messagePort.postMessage("Meow")\`,
74+
context,
75+
{ displayErrors: true }
76+
);
77+
`, {
78+
eval: true,
79+
workerData: { messagePort: channel.port2 },
80+
transferList: [channel.port2]
81+
});
82+
channel.port1.on(
83+
'message',
84+
(message) =>
85+
assert.strictEqual(message, 'Meow')
86+
);
87+
}

0 commit comments

Comments
 (0)