Skip to content

Commit

Permalink
src: support sync 'overlapped' stdio option
Browse files Browse the repository at this point in the history
Fix an oversight in the pull request that introduced the 'overlapped'
option to the asynchronous child process methods, and also add it to
the synchronous methods, like child_process.spawnSync().

Fixes: nodejs#48476
Refs: nodejs#29412
  • Loading branch information
bnoordhuis committed Jun 17, 2023
1 parent 0d725d6 commit d29036e
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
22 changes: 19 additions & 3 deletions src/spawn_sync.cc
Expand Up @@ -95,10 +95,12 @@ void SyncProcessOutputBuffer::set_next(SyncProcessOutputBuffer* next) {
SyncProcessStdioPipe::SyncProcessStdioPipe(SyncProcessRunner* process_handler,
bool readable,
bool writable,
bool overlapped,
uv_buf_t input_buffer)
: process_handler_(process_handler),
readable_(readable),
writable_(writable),
overlapped_(overlapped),
input_buffer_(input_buffer),

first_output_buffer_(nullptr),
Expand Down Expand Up @@ -202,6 +204,11 @@ bool SyncProcessStdioPipe::writable() const {
}


bool SyncProcessStdioPipe::overlapped() const {
return overlapped_;
}


uv_stdio_flags SyncProcessStdioPipe::uv_flags() const {
unsigned int flags;

Expand All @@ -210,6 +217,8 @@ uv_stdio_flags SyncProcessStdioPipe::uv_flags() const {
flags |= UV_READABLE_PIPE;
if (writable())
flags |= UV_WRITABLE_PIPE;
if (overlapped())
flags |= UV_OVERLAPPED_PIPE;

return static_cast<uv_stdio_flags>(flags);
}
Expand Down Expand Up @@ -897,7 +906,8 @@ int SyncProcessRunner::ParseStdioOption(int child_fd,
if (js_type->StrictEquals(env()->ignore_string())) {
return AddStdioIgnore(child_fd);

} else if (js_type->StrictEquals(env()->pipe_string())) {
} else if (js_type->StrictEquals(env()->pipe_string()) ||
js_type->StrictEquals(env()->overlapped_string())) {
Isolate* isolate = env()->isolate();
Local<String> rs = env()->readable_string();
Local<String> ws = env()->writable_string();
Expand All @@ -924,7 +934,8 @@ int SyncProcessRunner::ParseStdioOption(int child_fd,
}
}

return AddStdioPipe(child_fd, readable, writable, buf);
bool overlapped = js_type->StrictEquals(env()->overlapped_string());
return AddStdioPipe(child_fd, readable, writable, overlapped, buf);

} else if (js_type->StrictEquals(env()->inherit_string()) ||
js_type->StrictEquals(env()->fd_string())) {
Expand All @@ -951,12 +962,17 @@ int SyncProcessRunner::AddStdioIgnore(uint32_t child_fd) {
int SyncProcessRunner::AddStdioPipe(uint32_t child_fd,
bool readable,
bool writable,
bool overlapped,
uv_buf_t input_buffer) {
CHECK_LT(child_fd, stdio_count_);
CHECK(!stdio_pipes_[child_fd]);

std::unique_ptr<SyncProcessStdioPipe> h(
new SyncProcessStdioPipe(this, readable, writable, input_buffer));
new SyncProcessStdioPipe(this,
readable,
writable,
overlapped,
input_buffer));

int r = h->Initialize(uv_loop_);
if (r < 0) {
Expand Down
4 changes: 4 additions & 0 deletions src/spawn_sync.h
Expand Up @@ -76,6 +76,7 @@ class SyncProcessStdioPipe {
SyncProcessStdioPipe(SyncProcessRunner* process_handler,
bool readable,
bool writable,
bool overlapped,
uv_buf_t input_buffer);
~SyncProcessStdioPipe();

Expand All @@ -87,6 +88,7 @@ class SyncProcessStdioPipe {

inline bool readable() const;
inline bool writable() const;
inline bool overlapped() const;
inline uv_stdio_flags uv_flags() const;

inline uv_pipe_t* uv_pipe() const;
Expand Down Expand Up @@ -119,6 +121,7 @@ class SyncProcessStdioPipe {

bool readable_;
bool writable_;
bool overlapped_;
uv_buf_t input_buffer_;

SyncProcessOutputBuffer* first_output_buffer_;
Expand Down Expand Up @@ -182,6 +185,7 @@ class SyncProcessRunner {
inline int AddStdioPipe(uint32_t child_fd,
bool readable,
bool writable,
bool overlapped,
uv_buf_t input_buffer);
inline int AddStdioInheritFD(uint32_t child_fd, int inherit_fd);

Expand Down
11 changes: 11 additions & 0 deletions test/parallel/test-child-process-stdio-overlapped.js
Expand Up @@ -37,6 +37,17 @@ if (!require('fs').existsSync(exePath)) {
common.skip(exe + ' binary is not available');
}

// We can't synchronously write to the child (the 'input' and 'stdio' options
// conflict) but we can at least verify it starts up normally and is then
// terminated by the timer watchdog.
const { error } = child_process.spawnSync(exePath, [], {
stdio: ['overlapped', 'pipe', 'pipe'],
timeout: 42,
});

assert.ok(error);
assert.strictEqual(error.code, 'ETIMEDOUT');

const child = child_process.spawn(exePath, [], {
stdio: ['overlapped', 'pipe', 'pipe']
});
Expand Down

0 comments on commit d29036e

Please sign in to comment.