From d29036ed0232c4d8f5b136a1eaf99a0077ba35ba Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 17 Jun 2023 09:01:02 +0200 Subject: [PATCH] src: support sync 'overlapped' stdio option 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: https://github.com/nodejs/node/issues/48476 Refs: https://github.com/nodejs/node/pull/29412 --- src/spawn_sync.cc | 22 ++++++++++++++++--- src/spawn_sync.h | 4 ++++ .../test-child-process-stdio-overlapped.js | 11 ++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/spawn_sync.cc b/src/spawn_sync.cc index b3c0fabafdaad2..7f332f2efc2b3e 100644 --- a/src/spawn_sync.cc +++ b/src/spawn_sync.cc @@ -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), @@ -202,6 +204,11 @@ bool SyncProcessStdioPipe::writable() const { } +bool SyncProcessStdioPipe::overlapped() const { + return overlapped_; +} + + uv_stdio_flags SyncProcessStdioPipe::uv_flags() const { unsigned int flags; @@ -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(flags); } @@ -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 rs = env()->readable_string(); Local ws = env()->writable_string(); @@ -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())) { @@ -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 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) { diff --git a/src/spawn_sync.h b/src/spawn_sync.h index 81a2f2aaa899ba..4552019f4847b0 100644 --- a/src/spawn_sync.h +++ b/src/spawn_sync.h @@ -76,6 +76,7 @@ class SyncProcessStdioPipe { SyncProcessStdioPipe(SyncProcessRunner* process_handler, bool readable, bool writable, + bool overlapped, uv_buf_t input_buffer); ~SyncProcessStdioPipe(); @@ -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; @@ -119,6 +121,7 @@ class SyncProcessStdioPipe { bool readable_; bool writable_; + bool overlapped_; uv_buf_t input_buffer_; SyncProcessOutputBuffer* first_output_buffer_; @@ -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); diff --git a/test/parallel/test-child-process-stdio-overlapped.js b/test/parallel/test-child-process-stdio-overlapped.js index 5c48e7ee105792..4cefbc570b28c6 100644 --- a/test/parallel/test-child-process-stdio-overlapped.js +++ b/test/parallel/test-child-process-stdio-overlapped.js @@ -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'] });