From 7b6d4ff66d9d6490f2f45d39f4278c8ee6d7039c Mon Sep 17 00:00:00 2001 From: Thiago Bastos Date: Thu, 4 Feb 2016 19:04:06 +0100 Subject: [PATCH 1/2] Fix incorrect behaviour on Windows related to stdio pipes being read-write Unfortunately if we always always create the stdio pipes as R+W (instead of only R for stdin, and only W for stdout and stderr) child processes on windows start to behave incorrectly. For example, if you spawn the 'cat' program, write to it and then shutdown its stdin, the correct behaviour is for the child to receive EOF and exit. But if stdin is RW the child never exits on Windows, and you have to kill the process to force it to exit. Changing the stdin pipe to only `UV_CREATE_PIPE|UV_READABLE_PIPE` fixes the problem. The current solution assumes only the standard stdio fd's (0-2) are used. A more flexible solution may be in order, but would require an API change. --- src/process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/process.c b/src/process.c index 6780b04d..f1d2464f 100644 --- a/src/process.c +++ b/src/process.c @@ -111,7 +111,8 @@ static int luv_spawn(lua_State* L) { uv_stream_t* stream = luv_check_stream(L, -1); int err = uv_fileno((uv_handle_t*)stream, &fd); if (err == UV_EINVAL || err == UV_EBADF) { - options.stdio[i].flags = UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE; + options.stdio[i].flags = + UV_CREATE_PIPE | (i == 0 ? UV_READABLE_PIPE : UV_WRITABLE_PIPE); } else { options.stdio[i].flags = UV_INHERIT_STREAM; @@ -257,4 +258,3 @@ static int luv_kill(lua_State* L) { lua_pushinteger(L, ret); return 1; } - From 2fed9454ebb870548cef1081a1f8a3dd879c1e70 Mon Sep 17 00:00:00 2001 From: Thiago Bastos Date: Thu, 4 Feb 2016 21:54:37 +0100 Subject: [PATCH 2/2] Improve fix for stdio pipes --- src/process.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/process.c b/src/process.c index f1d2464f..d9395038 100644 --- a/src/process.c +++ b/src/process.c @@ -111,8 +111,14 @@ static int luv_spawn(lua_State* L) { uv_stream_t* stream = luv_check_stream(L, -1); int err = uv_fileno((uv_handle_t*)stream, &fd); if (err == UV_EINVAL || err == UV_EBADF) { - options.stdio[i].flags = - UV_CREATE_PIPE | (i == 0 ? UV_READABLE_PIPE : UV_WRITABLE_PIPE); + // stdin (fd 0) is read-only, stdout and stderr (fds 1 & 2) are + // write-only, and all fds > 2 are read-write + int flags = UV_CREATE_PIPE; + if (i == 0 || i > 2) + flags |= UV_READABLE_PIPE; + if (i != 0) + flags |= UV_WRITABLE_PIPE; + options.stdio[i].flags = flags; } else { options.stdio[i].flags = UV_INHERIT_STREAM;