Skip to content

Commit 67cacef

Browse files
committed
fix: fk stdin handling
1 parent 56b882a commit 67cacef

File tree

1 file changed

+45
-2
lines changed

1 file changed

+45
-2
lines changed

src/lib/commands/read-stdin.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,27 @@ export async function readStdin(stdinStream: typeof process.stdin = process.stdi
99
// The best showcase of what this does: https://stackoverflow.com/a/59024214
1010
const pipedIn = await fstat(0)
1111
.then((stat) => {
12+
if (process.env.STDIN_DEBUG) {
13+
console.error({
14+
stat,
15+
isFIFO: stat.isFIFO(),
16+
isSocket: stat.isSocket(),
17+
isCharDevice: stat.isCharacterDevice(),
18+
isRegularFile: stat.isFile(),
19+
});
20+
}
21+
1222
// isFIFO -> `node a | node b`
1323
// isFile -> `node a < file`
14-
return stat.isFIFO() || stat.isFile();
24+
// isSocket -> child processes (I think) [but we set a timeout of 50ms to avoid hanging]
25+
return stat.isFIFO() || stat.isFile() || (stat.isSocket() ? 50 : false);
1526
})
1627
.catch(() => false);
1728

29+
if (process.env.STDIN_DEBUG) {
30+
console.error({ isTTY: stdinStream.isTTY, pipedIn, readableEnd: stdinStream.readableEnded });
31+
}
32+
1833
// The isTTY params will be true if there is no piping into stdin
1934
// pipedIn is set if someone either runs `node a | node b`, or `node a < file`
2035
// if that is the case, isTTY will be undefined (???)
@@ -25,11 +40,39 @@ export async function readStdin(stdinStream: typeof process.stdin = process.stdi
2540

2641
const bufferChunks: Buffer[] = [];
2742

43+
const controller = new AbortController();
44+
45+
let timeout: NodeJS.Timeout | null = null;
46+
47+
if (typeof pipedIn === 'number') {
48+
timeout = setTimeout(() => {
49+
controller.abort();
50+
}, pipedIn).unref();
51+
}
52+
2853
stdinStream.on('data', (chunk) => {
2954
bufferChunks.push(chunk);
55+
56+
// If we got some data already, we can clear the timeout, as we will get more
57+
if (timeout) {
58+
clearTimeout(timeout);
59+
timeout = null;
60+
}
3061
});
3162

32-
await once(stdinStream, 'end');
63+
try {
64+
await once(stdinStream, 'end', { signal: controller.signal });
65+
} catch (error) {
66+
const casted = error as Error;
67+
68+
if (casted.name === 'AbortError') {
69+
return;
70+
}
71+
}
72+
73+
if (timeout) {
74+
clearTimeout(timeout);
75+
}
3376

3477
const concat = Buffer.concat(bufferChunks);
3578

0 commit comments

Comments
 (0)