nodejs / help

:sparkles: Need help with Node.js? File an Issue here. :rocket:
1.47k stars 282 forks source link

CreateProcess on windows, in addon, fails to show any output #4184

Closed d3x0r closed 7 months ago

d3x0r commented 1 year ago

Details

I have been working with creating processes on windows. I have a native addon which includes creating tasks. The default options for CreateProcess() on windows should pass the default console handles to the child process, which it can then use to generate output. When I use the same code in an addon, loaded by Node, I get no output to the console.

I have included two versions, native-test.zip is a simple .cc file that creates a process tasklist /? which is a utility included in windows, and the /? option shows its help. Included in the zip is a README.md that has building and running instructions.

testCreateProcessAddon.zip is a node addon, which uses node-gyp to build. extracting the zip, and going into the folder and running npm install compiles the code. Then there is a test script which is run with node test.js. It has testCreateProcess.cc which again launches tasklist /? the same as the other example. the test.js has a half second timeout, which should be long enough for the task to load and generate its output with lots of time to spare. This generates no output.

native-test.zip testCreateProcessAddon.zip

I tried to just include a version of the npm from npm pack but, this rejected the upload, and said I should use a file with an extension like (long list of extensions) which included ... .tgz, ... but still refused the file.

The full version of the addon has the ability to set pipes to capture the task output, so I can generally work around this; but I wanted to just run a task with no input handler specified and just let it log to the console, but the task refused to do so.

I tried to even do the create() function in the .cc files at the module init time, and it behaved the same way...

Does Node do something to the default standard handles to make them uninheritable? or maybe it closes them and replaces them with its own output handles? I'm totally guessing, but I don't understand what Node could be doing that causes this to fail.

Node.js version

I'm currently testing with a 19.4.0 version; but node greater than 9 is required for the addon to build correctly because it uses NODE_MODULE_INIT().

I don't expect any difference in behavior for any other version.

Example code

No response

Operating system

Windows 11, but I do expect the same behavior for any version of windows.

Scope

other?

Module and version

Not applicable.

d3x0r commented 1 year ago

Node IS setting the stdio handles as un-inheritable; this is another workaround/fix.

{
    SetHandleInformation( GetStdHandle( STD_INPUT_HANDLE  ), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) ;
    SetHandleInformation( GetStdHandle( STD_OUTPUT_HANDLE  ), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) ;
    SetHandleInformation( GetStdHandle( STD_ERROR_HANDLE  ), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) ;
}

There is also a function 'GetHandleInformation' which can be used to see if the handles are inheritable.

I expect this is 'working as expected', since it might affect node behavior for spawn/fork or something...

I did test back to the latest 14 (14.21.3, 16.20.0, 18.12.1, 20.3.0) and they all behave the same way.

d3x0r commented 7 months ago

Although this behavior is unexpected, now that I know that node sets stdio handles on windows and linux (on all systems?) to non-inheritable I can now handle launching sub-processes and letting them output to standard output without having to capture their output and manually echo it; that is I can re-enable the inheritable flags on stdin, stdout, and stderr for the short time of creating a new process. https://www.npmjs.com/package/sack.vfs