-
-
Notifications
You must be signed in to change notification settings - Fork 214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
input
option does not work with fast processes
#474
Comments
I am getting this error as well, from execa >= 2. I have tried with 0.x, 1.x, and it seems to work as expected. Once I install execa@2, it fails with the command not found. |
stdin
option does not work with Node >=16.7.0
stdin
option does not work with fast processes
@nickroberts I have updated my original message. The problem is actually not related to Node.js versions. Instead, this is happening when the process execute too fast. A discussion is currently happening about a way to fix this at nodejs/node#40085 |
The issue over at nodejs/node#40085 was closed and considered not a bug, as it can be handled by the application. Will execa handle it internally or is it left to be handled by the user? |
stdin
option does not work with fast processesinput
option does not work with fast processes
Yes, it is not a bug from Node.js. Namely, the This is a bug from Execa that we should ideally fix. I'm having some issue finding a reliable way to detect whether Instead, I'm thinking the proper way would be to create a stream from the |
Yeah, that sounds good to me. You could just use |
I took a stab at it, but realized the following problem:
This is confirmed in the code: This results in:
Strings and buffers are allowed, but only with I feel like this means we would need to write (then cleanup) a temporary file. Touching the filesystem seems a bit too much just to solve this bug. What are your thoughts on this @sindresorhus? Do you have any other idea on how to solve this problem? |
It says it accepts a socket too, so you could potentially create that: const net = require('net');
const { spawn } = require('child_process');
const server = net.createServer(function (socket) {
// Spawn your child process here and use the socket as a stdio stream
const child = spawn('command', [], {
stdio: ['pipe', socket, socket]
});
// Write to the child's stdin
child.stdin.write('Hello, child process!\n');
// Print the child's stdout/stderr
child.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
});
server.listen(function () {
const { port } = server.address();
// Connect to the server socket
const socket = net.connect(port);
// Write to the server socket (writes to the child's stdin)
socket.write('Hello, server socket!\n');
// Print the server socket's output (the child's stdout/stderr)
socket.on('data', (data) => {
console.log(`socket: ${data}`);
});
}); ChatGPT |
Otherwise, I don't think it's too bad to create a temporary file either. |
Could we maybe simply detect EPIPE and ignore it if it's in the first second (or less) of the process execution or something? |
Maybe we could wait for the |
Thanks for all those different ideas! :)
Using a socket is a creative solution, although using a temporary file might have the same result, but be more straightforward to implement.
I am concerned about the following issues:
I am not sure this would work, since it would only delay writing to Based on this, I am feeling like using a temporary file might be the "cleanest" (as in "bug-proof") way to implement this? |
I agree. A temporary file seems like the safest as there are a lot of unknowns with the other solutions. |
I took another stab at it, but encountered the following problem, which applies to both the temporary file and the socket solution: We could use sync I/O to create the temporary file, but this would make import { execa, createInput } from 'execa'
const input = await createInput('test')
await execa('command', { input }) 🤔 |
Another potential idea: calling a second child process that just outputs the string, then pipe its const childProcess = execa('printf', ['test'])
await execa('command', { stdin: childProcess.stdout }) Also, with the new Node.js permissions system, Execa would not require any additional One problem with this approach is that the first child process would also need to be "handled": errors, exit, etc. Another problem is to find a command which echoes a string (without appending a newline) that is cross-OS. For example,
As a side note, this is a very interesting problem to solve. :) |
I am starting to wonder whether this is something that should be fixed by Node.js core, so I opened nodejs/node#48786 to port the |
The discussion in core Node.js was very insightful. The first thing is: at the syscall level (using Linux as an example), So, calling The second thing is:
In all those cases, propagating As a conclusion, the current behavior is the proper one, and I think we should close this issue. |
This can be reproduced with:
This happens when the child process is too fast to finish. When this happens, Execa writes to the process
stdin
while it has already ended, which creates anEPIPE
error.Discussion about this happening at nodejs/node#40085
The text was updated successfully, but these errors were encountered: