Skip to content

Creation of full duplex pipe via spawn causes deadlock on Windows #29238

Closed
@haiyangwu

Description

  • v12.8.1:
  • 64-bit Windows 10:
  • Subsystem:

Recently tried to add windows support for mediasoup, https://github.com/haiyangwu/mediasoup-win, but found
Related Bug in LibUV, libuv/libuv#95,

Parent Process, node js:

    const spawnArgs = [ id ].concat(parameters);
    const spawnOptions =
    {
        detached : false,

        /*
            * fd 0 (stdin)   : Just ignore it.
            * fd 1 (stdout)  : Pipe it for 3rd libraries in the worker.
            *                  that log their own stuff.
            * fd 2 (stderr)  : Same as stdout.
            * fd 3 (channel) : Channel fd.
            */
        stdio : [ 'ignore', 'pipe', 'pipe', 'pipe' ]
    };

    // Closed flag.
    this._closed = false;

    // Create the mediasoup-worker child process.
    this._child = spawn(workerPath, spawnArgs, spawnOptions);

    // Channel instance.
    this._channel = new Channel(this._child.stdio[CHANNEL_FD]);
class Channel extends EnhancedEventEmitter
{
	constructor(socket)
	{
        // Read Channel responses/notifications from the worker.
		this._socket.on('data', (buffer) =>
		{
            // ....
        }
    }
}

Child Process, c++ :

        int err;
	this->uvHandle       = new uv_pipe_t;
	this->uvHandle->data = (void*)this;

	err = uv_pipe_init(DepLibUV::GetLoop(), this->uvHandle, 0);
	if (err != 0)
	{
		delete this->uvHandle;
		this->uvHandle = nullptr;

		MS_THROW_ERROR_STD("uv_pipe_init() failed: %s", uv_strerror(err));
	}

	err = uv_pipe_open(this->uvHandle, fd);
	if (err != 0)
	{
		uv_close(reinterpret_cast<uv_handle_t*>(this->uvHandle), static_cast<uv_close_cb>(onClose));

		MS_THROW_ERROR_STD("uv_pipe_open() failed: %s", uv_strerror(err));
	}

	// Start reading.
	err = uv_read_start(
	  reinterpret_cast<uv_stream_t*>(this->uvHandle),
	  static_cast<uv_alloc_cb>(onAlloc),
	  static_cast<uv_read_cb>(onRead));
	if (err != 0)
	{
		uv_close(reinterpret_cast<uv_handle_t*>(this->uvHandle), static_cast<uv_close_cb>(onClose));

		MS_THROW_ERROR_STD("uv_read_start() failed: %s", uv_strerror(err));
	}

This works like a champ on Linux/OSX, however, on Windows the payload from the child sometimes not gets sent.

already tried to change code in src/process_wrap.cc, and after test, my app works

    // ....
    } else if (type->StrictEquals(env->pipe_string())) {
#ifdef _WIN32
        options->stdio[i].flags =
            static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_READABLE_PIPE |
                                        UV_WRITABLE_PIPE | UV_OVERLAPPED_PIPE);
#else
        options->stdio[i].flags = static_cast<uv_stdio_flags>(
            UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE);
#endif
    } else if (type->StrictEquals(env->wrap_string())) {
    // ....

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    child_processIssues and PRs related to the child_process subsystem.windowsIssues and PRs related to the Windows platform.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions