into-stream icon indicating copy to clipboard operation
into-stream copied to clipboard

Can't use for stdio

Open RossComputerGuy opened this issue 6 years ago • 4 comments

Issuehunt badges

TypeError [ERR_INVALID_OPT_VALUE]: The value "Class {
  _reading: false,
  _callback: [Function: check],
  _readableState:
   ReadableState {
     objectMode: false,
     highWaterMark: 16384,
     buffer: BufferList { length: 0 },
     length: 0,
     pipes: null,
     pipesCount: 0,
     flowing: null,
     ended: false,
     endEmitted: false,
     reading: false,
     sync: true,
     needReadable: false,
     emittedReadable: false,
     readableListening: false,
     resumeScheduled: false,
     destroyed: false,
     defaultEncoding: 'utf8',
     awaitDrain: 0,
     readingMore: false,
     decoder: null,
     encoding: null },
  readable: true,
  _events: [Object: null prototype] {},
  _eventsCount: 0,
  _maxListeners: undefined,
  _from: [Function: reader] }" is invalid for option "stdio"
    at stdio.reduce (internal/child_process.js:953:13)
    at Array.reduce (<anonymous>)
    at _validateStdio (internal/child_process.js:880:17)
    at ChildProcess.spawn (internal/child_process.js:317:11)
    at Object.spawn (child_process.js:544:9)
    at executeCommand (/opt/os.js/node_modules/bluelight-settings-application/server.js:11:38)
    at WebSocket.ws.once.data (/opt/os.js/node_modules/bluelight-settings-application/server.js:16:22)
    at Object.onceWrapper (events.js:276:13)
    at WebSocket.emit (events.js:188:13)
    at Receiver.receiverOnMessage (/opt/os.js/node_modules/ws/lib/websocket.js:720:20)
    at Receiver.emit (events.js:188:13)
    at Receiver.dataMessage (/opt/os.js/node_modules/ws/lib/receiver.js:414:14)
    at Receiver.getData (/opt/os.js/node_modules/ws/lib/receiver.js:346:17)
    at Receiver.startLoop (/opt/os.js/node_modules/ws/lib/receiver.js:133:22)
    at Receiver._write (/opt/os.js/node_modules/ws/lib/receiver.js:69:10)
    at doWrite (_stream_writable.js:415:12)

There is a $30.00 open bounty on this issue. Add more on Issuehunt.

RossComputerGuy avatar Jan 08 '19 00:01 RossComputerGuy

Can you share a minimal test case that reproduces the issue?

sindresorhus avatar Jan 08 '19 01:01 sindresorhus

Part of my code:

child_process.spawn(cmd, args, Object.assign({stdio: [intoStream(sudoPassword + '\n'), 'pipe', 'pipe']}, opts || {}));

RossComputerGuy avatar Jan 08 '19 09:01 RossComputerGuy

@issuehunt has funded $30.00 to this issue.


IssueHuntBot avatar Mar 20 '19 08:03 IssueHuntBot

It appears that options.stdio is rather particular about the type of Streams that are allowed to be passed. From the docs (emphasis added):

Share a readable or writable stream that refers to a tty, file, socket, or a pipe with the child process.

And the corresponding source code from nodejs/node:

function getHandleWrapType(stream) {
  if (stream instanceof Pipe) return 'pipe';
  if (stream instanceof TTY) return 'tty';
  if (stream instanceof TCP) return 'tcp';
  if (stream instanceof UDP) return 'udp';

  return false;
}

It would appear that the Stream returned from the from2 package fails these instanceof checks and is therefore not compatible with options.stdio.

Here is a test that demonstrates the failure:

// Fails

test('works with stdio', async t => {
	const input = 'hello, world';
	await new Promise(resolve => {
		const stream = intoStream(input);
		const proc = spawn('cat', {stdio: [stream, 'pipe', 'pipe']});
		proc.stdout.on('data', data => {
			t.assert(data.toString('utf8') === input);
		});
		proc.on('exit', code => {
			t.assert(code === 0);
			resolve();
		});
	});
});

And a demonstration of the correct type of Stream being used:

// Passes; uses a ReadableStream with underlying fd rather than intoStream

test('works with stdio', async t => {
	const input = 'hello, world';
	await new Promise(resolve => {
		const stream = fs.createReadStream('fixture');
		stream.on('open', () => {
			const proc = spawn('cat', {stdio: [stream, 'pipe', 'pipe']});
			proc.stdout.on('data', data => {
				t.assert(data.toString('utf8') === input);
			});
			proc.on('exit', code => {
				t.assert(code === 0);
				resolve();
			});
		});
	});
});

I am relatively new to streams and there could be a hole in my knowledge that is preventing me from seeing a solution. Otherwise, I would recommend closing this issue as "Can't fix."

mjswensen avatar Oct 11 '19 17:10 mjswensen