diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2013-05-10 11:19:17 -0700 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2013-06-06 17:42:07 +0200 |
commit | 8a3d0c8b9103b8aa6d0e06a4fc018cb8fb8c8ab9 (patch) | |
tree | 28346c8b166241f1840963f23e692b04636a22fb | |
parent | bf16141eeb03ca4c942237b4535c46f5d244ed27 (diff) | |
download | node-8a3d0c8b9103b8aa6d0e06a4fc018cb8fb8c8ab9.tar.gz |
child_process: fix handle delivery
node.js and libuv depend on the fact that none of the supported systems
ever emit more than one SCM_RIGHTS message from a recvmsg() syscall.
SCM_RIGHTS messages are never coalesced. SCM_RIGHTS and normal messages
however _are_ coalesced. That is, recvmsg() might return this:
recvmsg(); // { "message-with-fd", "message", "message" }
The operating system implicitly breaks pending messages along
SCM_RIGHTS boundaries. Most Unices break before such messages but Linux
also breaks _after_ them. When the sender looks like this:
sendmsg("message");
sendmsg("message-with-fd");
sendmsg("message");
Then on most Unices the receiver sees messages arriving like this:
recvmsg(); // { "message" }
recvmsg(); // { "message-with-fd", "message" }
The bug fix in commit 9352c19 assumes this behavior. On Linux however,
those messages can also come in like this:
recvmsg(); // { "message", "message-with-fd" }
recvmsg(); // { "message" }
In other words, it's incorrect to assume that the file descriptor is
always attached to the first message. This commit makes node wise up.
This is a back-port of commit 21bd456 from the v0.10 branch. The test
has been dropped as it's not compatible with the v0.8 process model.
Fixes #5330.
Conflicts:
lib/child_process.js
-rw-r--r-- | lib/child_process.js | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/lib/child_process.js b/lib/child_process.js index d4b58e770..0b2e9b37f 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -292,7 +292,13 @@ function setupChannel(target, channel) { var json = jsonBuffer.slice(start, i); var message = JSON.parse(json); - handleMessage(target, message, recvHandle); + // There will be at most one NODE_HANDLE message in every chunk we + // read because SCM_RIGHTS messages don't get coalesced. Make sure + // that we deliver the handle with the right message however. + if (message && message.cmd === 'NODE_HANDLE') + handleMessage(target, message, recvHandle); + else + handleMessage(target, message, undefined); start = i + 1; } |