Skip to content

Issue passing file descriptors in OS X #7512

Closed
@santigimeno

Description

@santigimeno
  • Version: v7.0.0-pre
  • Platform: OS X 10.11.5
  • Subsystem: child_process

The test-cluster-net-send.js test is sometimes failing when running the test suite in my OS X with the following output:

=== release test-cluster-net-send ===                                          
Path: parallel/test-cluster-net-send
[32787] master
[32789] worker

assert.js:90
  throw new assert.AssertionError({
  ^
AssertionError: false == true
    at process.<anonymous> (/Users/sgimeno/node/node/test/parallel/test-cluster-net-send.js:29:12)
    at process.g (events.js:286:16)
    at emitOne (events.js:101:20)
    at process.emit (events.js:188:7)
Command: out/Release/node /Users/sgimeno/node/node/test/parallel/test-cluster-net-send.js

After investigating the issue it looks like that the error happens only when the fd that passes the worker to the master is closed before it is received in the master process. The following patch, that closes the fd only after receiving the NODE_HANDLE_ACK message fixes the issue for me.

diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js
index 789c29e..44a245e 100644
--- a/lib/internal/child_process.js
+++ b/lib/internal/child_process.js
@@ -96,8 +96,8 @@ const handleConversion = {

     postSend: function(handle, options) {
       // Close the Socket handle after sending it
-      if (handle && !options.keepOpen)
-        handle.close();
+      //if (handle && !options.keepOpen)
+      //  global_handle = handle;
     },

     got: function(message, handle, emit) {
@@ -465,6 +465,11 @@ function setupChannel(target, channel) {
   target.on('internalMessage', function(message, handle) {
     // Once acknowledged - continue sending handles.
     if (message.cmd === 'NODE_HANDLE_ACK') {
+      if (target._pending_handle) {
+        target._pending_handle.close();
+        target._pending_handle = null;
+      }
+
       assert(Array.isArray(target._handleQueue));
       var queue = target._handleQueue;
       target._handleQueue = null;
@@ -615,8 +620,13 @@ function setupChannel(target, channel) {
       req.oncomplete = function() {
         if (this.async === true)
           control.unref();
-        if (obj && obj.postSend)
+        if (obj && obj.postSend) {
           obj.postSend(handle, options);
+          if (handle && !options.keepOpen) {
+            assert(!target._pending_handle);
+            target._pending_handle = handle;
+          }
+        }

This seems strange to me as my understanding was that closing the file descriptor after sending it was safe (at least in my Linux box I have not been able to reproduce the same issue). Thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    child_processIssues and PRs related to the child_process subsystem.macosIssues and PRs related to the macOS platform / OSX.netIssues and PRs related to the net subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions