1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-23 15:49:44 -05:00

fix: read raw stdin to prevent buffering (regression) (#14704)

This commit is contained in:
David Sherret 2022-05-23 12:35:02 -04:00 committed by GitHub
parent 69be1f3cf7
commit b65d5024ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 29 additions and 17 deletions

View file

@ -85,3 +85,9 @@ itest!(task_deno_exe_no_env {
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
env_clear: true,
});
itest!(task_piped_stdin {
args_vec: vec!["task", "-q", "--config", "task/deno.json", "piped"],
output: "task/task_piped_stdin.out",
envs: vec![("NO_COLOR".to_string(), "1".to_string())],
});

View file

@ -4,6 +4,7 @@
"echo": "echo 1",
"deno_echo": "deno eval 'console.log(5)'",
"strings": "deno run main.ts && deno eval \"console.log(\\\"test\\\")\"",
"piped": "echo 12345 | (deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)' && deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)')",
"exit_code_5": "echo $(echo 10 ; exit 2) && exit 5"
}
}

View file

@ -7,5 +7,7 @@ Available tasks:
echo 1
- exit_code_5
echo $(echo 10 ; exit 2) && exit 5
- piped
echo 12345 | (deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)' && deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)')
- strings
deno run main.ts && deno eval "console.log(\"test\")"

View file

@ -9,5 +9,7 @@ Available tasks:
echo 1
- exit_code_5
echo $(echo 10 ; exit 2) && exit 5
- piped
echo 12345 | (deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)' && deno eval 'const b = new Uint8Array(1);Deno.stdin.readSync(b);console.log(b)')
- strings
deno run main.ts && deno eval "console.log(\"test\")"

View file

@ -0,0 +1,3 @@
[WILDCARD]
Uint8Array(1) [ 49 ]
Uint8Array(1) [ 50 ]

View file

@ -116,7 +116,9 @@ pub fn init_stdio(stdio: Stdio) -> Extension {
let t = &mut state.resource_table;
t.add(StdFileResource::stdio(
match stdio.stdin {
StdioPipe::Inherit => StdFileResourceInner::Stdin,
StdioPipe::Inherit => StdFileResourceInner::Stdin(Arc::new(
Mutex::new(STDIN_HANDLE.try_clone().unwrap()),
)),
StdioPipe::File(pipe) => StdFileResourceInner::file(pipe),
},
"stdin",
@ -296,14 +298,14 @@ impl Resource for ChildStderrResource {
#[derive(Clone)]
enum StdFileResourceInner {
File(Arc<Mutex<StdFile>>),
Stdin(Arc<Mutex<StdFile>>),
// Ideally we would store stdio as an StdFile, but we get some Windows
// specific functionality for free by using Rust std's wrappers. So we
// take a bit of a complexity hit here in order to not have to duplicate
// the functionality in Rust's std/src/sys/windows/stdio.rs
Stdin,
Stdout,
Stderr,
File(Arc<Mutex<StdFile>>),
}
impl StdFileResourceInner {
@ -313,13 +315,12 @@ impl StdFileResourceInner {
pub fn with_file<R>(&self, mut f: impl FnMut(&mut StdFile) -> R) -> R {
match self {
Self::Stdin => f(&mut STDIN_HANDLE.try_clone().unwrap()),
Self::Stdout => f(&mut STDOUT_HANDLE.try_clone().unwrap()),
Self::Stderr => f(&mut STDERR_HANDLE.try_clone().unwrap()),
Self::File(file) => {
Self::File(file) | Self::Stdin(file) => {
let mut file = file.lock();
f(&mut file)
}
Self::Stdout => f(&mut STDOUT_HANDLE.try_clone().unwrap()),
Self::Stderr => f(&mut STDERR_HANDLE.try_clone().unwrap()),
}
}
@ -344,10 +345,9 @@ impl StdFileResourceInner {
impl Read for StdFileResourceInner {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
match self {
Self::File(file) | Self::Stdin(file) => file.lock().read(buf),
Self::Stdout => Err(ErrorKind::Unsupported.into()),
Self::Stderr => Err(ErrorKind::Unsupported.into()),
Self::Stdin => std::io::stdin().read(buf),
Self::File(file) => file.lock().read(buf),
}
}
}
@ -355,19 +355,19 @@ impl Read for StdFileResourceInner {
impl Write for StdFileResourceInner {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
match self {
Self::File(file) => file.lock().write(buf),
Self::Stdin(_) => Err(ErrorKind::Unsupported.into()),
Self::Stdout => std::io::stdout().write(buf),
Self::Stderr => std::io::stderr().write(buf),
Self::Stdin => Err(ErrorKind::Unsupported.into()),
Self::File(file) => file.lock().write(buf),
}
}
fn flush(&mut self) -> std::io::Result<()> {
match self {
Self::File(file) => file.lock().flush(),
Self::Stdin(_) => Err(ErrorKind::Unsupported.into()),
Self::Stdout => std::io::stdout().flush(),
Self::Stderr => std::io::stderr().flush(),
Self::Stdin => Err(ErrorKind::Unsupported.into()),
Self::File(file) => file.lock().flush(),
}
}
}
@ -397,10 +397,8 @@ impl StdFileResource {
pub fn std_file(&self) -> Arc<Mutex<StdFile>> {
match &self.inner {
StdFileResourceInner::File(fs_file) => fs_file.clone(),
StdFileResourceInner::Stdin => {
Arc::new(Mutex::new(STDIN_HANDLE.try_clone().unwrap()))
}
StdFileResourceInner::File(fs_file)
| StdFileResourceInner::Stdin(fs_file) => fs_file.clone(),
StdFileResourceInner::Stdout => {
Arc::new(Mutex::new(STDOUT_HANDLE.try_clone().unwrap()))
}