diff --git a/lib/internal/bootstrap/switches/is_main_thread.js b/lib/internal/bootstrap/switches/is_main_thread.js index 08623898edafac..452031e1519f41 100644 --- a/lib/internal/bootstrap/switches/is_main_thread.js +++ b/lib/internal/bootstrap/switches/is_main_thread.js @@ -157,7 +157,11 @@ function getStdin() { case 'FILE': const fs = require('fs'); - stdin = new fs.ReadStream(null, { fd: fd, autoClose: false }); + stdin = new fs.ReadStream(null, { + fd: fd, + autoClose: false, + manualStart: true + }); break; case 'PIPE': diff --git a/lib/internal/streams/readable.js b/lib/internal/streams/readable.js index a004ce20d0aeb8..bed5aa73dde4d2 100644 --- a/lib/internal/streams/readable.js +++ b/lib/internal/streams/readable.js @@ -203,7 +203,8 @@ function Readable(options) { Stream.call(this, options); destroyImpl.construct(this, () => { - maybeReadMore(this, this._readableState); + if (!options || !options.manualStart) + maybeReadMore(this, this._readableState); }); } diff --git a/test/parallel/test-stdin-from-file-spawn.js b/test/parallel/test-stdin-from-file-spawn.js new file mode 100644 index 00000000000000..12c235fcfeb081 --- /dev/null +++ b/test/parallel/test-stdin-from-file-spawn.js @@ -0,0 +1,42 @@ +'use strict'; +const common = require('../common'); +const process = require('process'); + +let defaultShell; +if (process.platform === 'linux' || process.platform === 'darwin') { + defaultShell = '/bin/sh'; +} else if (process.platform === 'win32') { + defaultShell = 'cmd.exe'; +} else { + common.skip('This is test exists only on Linux/Win32/OSX'); +} + +const { execSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); +const tmpdir = require('../common/tmpdir'); + +const tmpDir = tmpdir.path; +tmpdir.refresh(); +const tmpCmdFile = path.join(tmpDir, 'test-stdin-from-file-spawn-cmd'); +const tmpJsFile = path.join(tmpDir, 'test-stdin-from-file-spawn.js'); +fs.writeFileSync(tmpCmdFile, 'echo hello'); +fs.writeFileSync(tmpJsFile, ` +'use strict'; +const { spawn } = require('child_process'); +// Reference the object to invoke the getter +process.stdin; +setTimeout(() => { + let ok = false; + const child = spawn(process.env.SHELL || '${defaultShell}', + [], { stdio: ['inherit', 'pipe'] }); + child.stdout.on('data', () => { + ok = true; + }); + child.on('close', () => { + process.exit(ok ? 0 : -1); + }); +}, 100); +`); + +execSync(`${process.argv[0]} ${tmpJsFile} < ${tmpCmdFile}`); diff --git a/test/parallel/test-stream-manualstart.js b/test/parallel/test-stream-manualstart.js new file mode 100644 index 00000000000000..2c7442a5538db8 --- /dev/null +++ b/test/parallel/test-stream-manualstart.js @@ -0,0 +1,20 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const fs = require('fs'); + +fs.promises.open(__filename).then(common.mustCall((fd) => { + const rs = new fs.ReadStream(null, { + fd: fd, + manualStart: false + }); + setTimeout(() => assert(rs.bytesRead > 0), common.platformTimeout(10)); +})); + +fs.promises.open(__filename).then(common.mustCall((fd) => { + const rs = new fs.ReadStream(null, { + fd: fd, + manualStart: true + }); + setTimeout(() => assert(rs.bytesRead === 0), common.platformTimeout(10)); +}));