summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2013-05-10 11:19:17 -0700
committerBen Noordhuis <info@bnoordhuis.nl>2013-06-06 17:42:07 +0200
commit8a3d0c8b9103b8aa6d0e06a4fc018cb8fb8c8ab9 (patch)
tree28346c8b166241f1840963f23e692b04636a22fb
parentbf16141eeb03ca4c942237b4535c46f5d244ed27 (diff)
downloadnode-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.js8
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;
}