Skip to content

Commit

Permalink
child_process: add 'overlapped' stdio flag
Browse files Browse the repository at this point in the history
The 'overlapped' value sets the UV_OVERLAPPED_PIPE libuv flag in the
child process stdio.

Fixes: nodejs#29238
  • Loading branch information
tarruda committed Dec 31, 2020
1 parent c380ee6 commit 5972bd6
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 8 deletions.
19 changes: 13 additions & 6 deletions doc/api/child_process.md
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,7 @@ equal to `['pipe', 'pipe', 'pipe']`.
For convenience, `options.stdio` may be one of the following strings:

* `'pipe'`: equivalent to `['pipe', 'pipe', 'pipe']` (the default)
* `'overlapped'`: equivalent to `['overlapped', 'overlapped', 'overlapped']`
* `'ignore'`: equivalent to `['ignore', 'ignore', 'ignore']`
* `'inherit'`: equivalent to `['inherit', 'inherit', 'inherit']` or `[0, 1, 2]`

Expand All @@ -688,7 +689,13 @@ pipes between the parent and child. The value is one of the following:
`child_process` object as [`subprocess.stdio[fd]`][`subprocess.stdio`]. Pipes
created for fds 0, 1, and 2 are also available as [`subprocess.stdin`][],
[`subprocess.stdout`][] and [`subprocess.stderr`][], respectively.
2. `'ipc'`: Create an IPC channel for passing messages/file descriptors
2. `'overlapped'`: Same as `'pipe'` except that the `FILE_FLAG_OVERLAPPED` flag
is set on the handle. This is necessary for overlapped I/O on the child
process's stdio handles. See the
[docs](https://docs.microsoft.com/en-us/windows/win32/fileio/synchronous-and-asynchronous-i-o)
for more details. This is exactly the same as `'pipe'` on non-Windows
systems.
3. `'ipc'`: Create an IPC channel for passing messages/file descriptors
between parent and child. A [`ChildProcess`][] may have at most one IPC
stdio file descriptor. Setting this option enables the
[`subprocess.send()`][] method. If the child is a Node.js process, the
Expand All @@ -699,25 +706,25 @@ pipes between the parent and child. The value is one of the following:
Accessing the IPC channel fd in any way other than [`process.send()`][]
or using the IPC channel with a child process that is not a Node.js instance
is not supported.
3. `'ignore'`: Instructs Node.js to ignore the fd in the child. While Node.js
4. `'ignore'`: Instructs Node.js to ignore the fd in the child. While Node.js
will always open fds 0, 1, and 2 for the processes it spawns, setting the fd
to `'ignore'` will cause Node.js to open `/dev/null` and attach it to the
child's fd.
4. `'inherit'`: Pass through the corresponding stdio stream to/from the
5. `'inherit'`: Pass through the corresponding stdio stream to/from the
parent process. In the first three positions, this is equivalent to
`process.stdin`, `process.stdout`, and `process.stderr`, respectively. In
any other position, equivalent to `'ignore'`.
5. {Stream} object: Share a readable or writable stream that refers to a tty,
6. {Stream} object: Share a readable or writable stream that refers to a tty,
file, socket, or a pipe with the child process. The stream's underlying
file descriptor is duplicated in the child process to the fd that
corresponds to the index in the `stdio` array. The stream must have an
underlying descriptor (file streams do not until the `'open'` event has
occurred).
6. Positive integer: The integer value is interpreted as a file descriptor
7. Positive integer: The integer value is interpreted as a file descriptor
that is currently open in the parent process. It is shared with the child
process, similar to how {Stream} objects can be shared. Passing sockets
is not supported on Windows.
7. `null`, `undefined`: Use default value. For stdio fds 0, 1, and 2 (in other
8. `null`, `undefined`: Use default value. For stdio fds 0, 1, and 2 (in other
words, stdin, stdout, and stderr) a pipe is created. For fd 3 and up, the
default is `'ignore'`.

Expand Down
6 changes: 4 additions & 2 deletions lib/internal/child_process.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ function stdioStringToArray(stdio, channel) {

switch (stdio) {
case 'ignore':
case 'overlapped':
case 'pipe': ArrayPrototypePush(options, stdio, stdio, stdio); break;
case 'inherit': ArrayPrototypePush(options, 0, 1, 2); break;
default:
Expand Down Expand Up @@ -976,9 +977,10 @@ function getValidStdio(stdio, sync) {

if (stdio === 'ignore') {
ArrayPrototypePush(acc, { type: 'ignore' });
} else if (stdio === 'pipe' || (typeof stdio === 'number' && stdio < 0)) {
} else if (stdio === 'pipe' || stdio === 'overlapped' ||
(typeof stdio === 'number' && stdio < 0)) {
const a = {
type: 'pipe',
type: stdio === 'overlapped' ? 'overlapped' : 'pipe',
readable: i === 0,
writable: i !== 0
};
Expand Down
1 change: 1 addition & 0 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ constexpr size_t kFsStatsBufferLength =
V(options_string, "options") \
V(order_string, "order") \
V(output_string, "output") \
V(overlapped_string, "overlapped") \
V(parse_error_string, "Parse Error") \
V(password_string, "password") \
V(path_string, "path") \
Expand Down
5 changes: 5 additions & 0 deletions src/process_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ class ProcessWrap : public HandleWrap {
options->stdio[i].flags = static_cast<uv_stdio_flags>(
UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE);
options->stdio[i].data.stream = StreamForWrap(env, stdio);
} else if (type->StrictEquals(env->overlapped_string())) {
options->stdio[i].flags = static_cast<uv_stdio_flags>(
UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE |
UV_OVERLAPPED_PIPE);
options->stdio[i].data.stream = StreamForWrap(env, stdio);
} else if (type->StrictEquals(env->wrap_string())) {
options->stdio[i].flags = UV_INHERIT_STREAM;
options->stdio[i].data.stream = StreamForWrap(env, stdio);
Expand Down

0 comments on commit 5972bd6

Please sign in to comment.