Skip to content

Commit ab6c09b

Browse files
addaleaxTrott
authored andcommitted
process: provide dummy stdio for non-console Windows apps
The only known condition where we could not provide appropriate stdio streams so far were non-console Windows applications. Since this issue has come up a few times in our issue tracker now, switch to providing dummy streams for these cases instead. If there are other valid cases in which `uv_guess_handle` fails, and where there is a more sensible way to provide stdio, we’ll probably still find out because the streams don’t work properly either way. Refs: nodejs/help#1251 PR-URL: #20640 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Luigi Pinca <[email protected]>
1 parent 54f8453 commit ab6c09b

File tree

4 files changed

+68
-26
lines changed

4 files changed

+68
-26
lines changed

doc/api/errors.md

+22-14
Original file line numberDiff line numberDiff line change
@@ -1795,20 +1795,6 @@ An attempt was made to load a module with an unknown or unsupported format.
17951795
An invalid or unknown process signal was passed to an API expecting a valid
17961796
signal (such as [`subprocess.kill()`][]).
17971797

1798-
<a id="ERR_UNKNOWN_STDIN_TYPE"></a>
1799-
### ERR_UNKNOWN_STDIN_TYPE
1800-
1801-
An attempt was made to launch a Node.js process with an unknown `stdin` file
1802-
type. This error is usually an indication of a bug within Node.js itself,
1803-
although it is possible for user code to trigger it.
1804-
1805-
<a id="ERR_UNKNOWN_STREAM_TYPE"></a>
1806-
### ERR_UNKNOWN_STREAM_TYPE
1807-
1808-
An attempt was made to launch a Node.js process with an unknown `stdout` or
1809-
`stderr` file type. This error is usually an indication of a bug within Node.js
1810-
itself, although it is possible for user code to trigger it.
1811-
18121798
<a id="ERR_V8BREAKITERATOR"></a>
18131799
### ERR_V8BREAKITERATOR
18141800

@@ -2065,6 +2051,28 @@ kind of internal Node.js error that should not typically be triggered by user
20652051
code. Instances of this error point to an internal bug within the Node.js
20662052
binary itself.
20672053

2054+
<a id="ERR_UNKNOWN_STDIN_TYPE"></a>
2055+
### ERR_UNKNOWN_STDIN_TYPE
2056+
<!-- YAML
2057+
added: v8.0.0
2058+
removed: REPLACEME
2059+
-->
2060+
2061+
An attempt was made to launch a Node.js process with an unknown `stdin` file
2062+
type. This error is usually an indication of a bug within Node.js itself,
2063+
although it is possible for user code to trigger it.
2064+
2065+
<a id="ERR_UNKNOWN_STREAM_TYPE"></a>
2066+
### ERR_UNKNOWN_STREAM_TYPE
2067+
<!-- YAML
2068+
added: v8.0.0
2069+
removed: REPLACEME
2070+
-->
2071+
2072+
An attempt was made to launch a Node.js process with an unknown `stdout` or
2073+
`stderr` file type. This error is usually an indication of a bug within Node.js
2074+
itself, although it is possible for user code to trigger it.
2075+
20682076
<a id="ERR_VALUE_OUT_OF_RANGE"></a>
20692077
### ERR_VALUE_OUT_OF_RANGE
20702078
<!-- YAML

lib/internal/errors.js

-3
Original file line numberDiff line numberDiff line change
@@ -905,10 +905,7 @@ E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s', TypeError);
905905
E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension: %s', Error);
906906
E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s', RangeError);
907907
E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s', TypeError);
908-
E('ERR_UNKNOWN_STDIN_TYPE', 'Unknown stdin file type', Error);
909908

910-
// This should probably be a `TypeError`.
911-
E('ERR_UNKNOWN_STREAM_TYPE', 'Unknown stream file type', Error);
912909
E('ERR_V8BREAKITERATOR',
913910
'Full ICU data not installed. See https://github.com/nodejs/node/wiki/Intl',
914911
Error);

lib/internal/process/stdio.js

+19-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
'use strict';
22

3-
const {
4-
ERR_UNKNOWN_STDIN_TYPE,
5-
ERR_UNKNOWN_STREAM_TYPE
6-
} = require('internal/errors').codes;
7-
83
exports.setupProcessStdio = setupProcessStdio;
94
exports.getMainThreadStdio = getMainThreadStdio;
105

@@ -87,8 +82,11 @@ function getMainThreadStdio() {
8782
break;
8883

8984
default:
90-
// Probably an error on in uv_guess_handle()
91-
throw new ERR_UNKNOWN_STDIN_TYPE();
85+
// Provide a dummy contentless input for e.g. non-console
86+
// Windows applications.
87+
const { Readable } = require('stream');
88+
stdin = new Readable({ read() {} });
89+
stdin.push(null);
9290
}
9391

9492
// For supporting legacy API we put the FD here.
@@ -123,6 +121,12 @@ function getMainThreadStdio() {
123121
return stdin;
124122
}
125123

124+
exports.resetStdioForTesting = function() {
125+
stdin = undefined;
126+
stdout = undefined;
127+
stderr = undefined;
128+
};
129+
126130
return {
127131
getStdout,
128132
getStderr,
@@ -199,8 +203,14 @@ function createWritableStdioStream(fd) {
199203
break;
200204

201205
default:
202-
// Probably an error on in uv_guess_handle()
203-
throw new ERR_UNKNOWN_STREAM_TYPE();
206+
// Provide a dummy black-hole output for e.g. non-console
207+
// Windows applications.
208+
const { Writable } = require('stream');
209+
stream = new Writable({
210+
write(buf, enc, cb) {
211+
cb();
212+
}
213+
});
204214
}
205215

206216
// For supporting legacy API we put the FD here.

test/parallel/test-dummy-stdio.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const child_process = require('child_process');
5+
6+
if (common.isWindows)
7+
common.skip('fs.closeSync(n) does not close stdio on Windows');
8+
9+
function runTest(fd, streamName, testOutputStream, expectedName) {
10+
const result = child_process.spawnSync(process.execPath, [
11+
'--expose-internals',
12+
'-e', `
13+
require('internal/process/stdio').resetStdioForTesting();
14+
fs.closeSync(${fd});
15+
const ctorName = process.${streamName}.constructor.name;
16+
process.${testOutputStream}.write(ctorName);
17+
`]);
18+
assert.strictEqual(result[testOutputStream].toString(), expectedName,
19+
`stdout:\n${result.stdout}\nstderr:\n${result.stderr}\n` +
20+
`while running test with fd = ${fd}`);
21+
if (testOutputStream !== 'stderr')
22+
assert.strictEqual(result.stderr.toString(), '');
23+
}
24+
25+
runTest(0, 'stdin', 'stdout', 'Readable');
26+
runTest(1, 'stdout', 'stderr', 'Writable');
27+
runTest(2, 'stderr', 'stdout', 'Writable');

0 commit comments

Comments
 (0)