Skip to content

Commit c51ab88

Browse files
committed
Fix close method on child writer not closing
Fixes a bug where `child.stdin:close()` on a child process created by `process.create()` did not actually close the `stdin`, this caused processes which read from stdin until EOF to wait indefinitely. On Unix, calling `close` on `async-process::ChildStdin` does not actually close the underyling writer. This is due to it using `async_io::Async` under the hood on Unix, whose `close` implementation just flushes the underlying writer. This has been fixed dropping the `ChildStdin` on close, which will close the underlying writer. An existing test has been updated to catch this bug.
1 parent 43484f1 commit c51ab88

File tree

2 files changed

+12
-12
lines changed

2 files changed

+12
-12
lines changed

crates/lune-std-process/src/create/child_writer.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,36 +10,33 @@ use mlua::prelude::*;
1010
// Inner (plumbing) implementation
1111

1212
#[derive(Debug)]
13-
enum ChildWriterInner {
14-
None,
15-
Stdin(AsyncChildStdin),
16-
}
13+
struct ChildWriterInner(Option<AsyncChildStdin>);
1714

1815
impl ChildWriterInner {
1916
async fn write(&mut self, data: Vec<u8>) -> Result<(), std::io::Error> {
20-
match self {
21-
ChildWriterInner::None => Ok(()),
22-
ChildWriterInner::Stdin(stdin) => stdin.write_all(&data).await,
17+
if let Some(stdin) = self.0.as_mut() {
18+
stdin.write_all(&data).await?;
2319
}
20+
Ok(())
2421
}
2522

2623
async fn close(&mut self) -> Result<(), std::io::Error> {
27-
match self {
28-
ChildWriterInner::None => Ok(()),
29-
ChildWriterInner::Stdin(stdin) => stdin.close().await,
24+
if let Some(mut stdin) = self.0.take() {
25+
stdin.flush().await?;
3026
}
27+
Ok(())
3128
}
3229
}
3330

3431
impl From<AsyncChildStdin> for ChildWriterInner {
3532
fn from(stdin: AsyncChildStdin) -> Self {
36-
ChildWriterInner::Stdin(stdin)
33+
ChildWriterInner(Some(stdin))
3734
}
3835
}
3936

4037
impl From<Option<AsyncChildStdin>> for ChildWriterInner {
4138
fn from(stdin: Option<AsyncChildStdin>) -> Self {
42-
stdin.map_or(Self::None, Into::into)
39+
ChildWriterInner(stdin)
4340
}
4441
}
4542

tests/process/create/stream.luau

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ catChild.stdin:write(expected)
99
catChild.stdin:close()
1010
local catOutput = catChild.stdout:read(#expected)
1111

12+
-- Make sure the child exits
13+
catChild:status()
14+
1215
assert(
1316
expected == catOutput,
1417
"Failed to write to stdin or read from stdout of child process!"

0 commit comments

Comments
 (0)