From bee55fcd20b4919f2d6b4817ce33d1a09e6bcadc Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Sun, 23 Dec 2018 13:53:29 +0900 Subject: [PATCH] make stdout unbuffered (#1355) --- BUILD.gn | 2 ++ Cargo.lock | 2 ++ Cargo.toml | 2 ++ src/resources.rs | 27 +++++++++++++++++++++++++-- tests/unbuffered_stderr.test | 3 +++ tests/unbuffered_stderr.ts | 3 +++ tests/unbuffered_stderr.ts.out | 1 + tests/unbuffered_stdout.test | 2 ++ tests/unbuffered_stdout.ts | 3 +++ tests/unbuffered_stdout.ts.out | 1 + 10 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 tests/unbuffered_stderr.test create mode 100644 tests/unbuffered_stderr.ts create mode 100644 tests/unbuffered_stderr.ts.out create mode 100644 tests/unbuffered_stdout.test create mode 100644 tests/unbuffered_stdout.ts create mode 100644 tests/unbuffered_stdout.ts.out diff --git a/BUILD.gn b/BUILD.gn index 69c1b741fc..ec7da8c386 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -42,6 +42,8 @@ main_extern = [ "$rust_build:tokio_process", "$rust_build:tokio_threadpool", "$rust_build:url", + "$rust_build:kernel32", + "$rust_build:winapi", "//build_extra/flatbuffers/rust:flatbuffers", ] diff --git a/Cargo.lock b/Cargo.lock index d4600715b1..6cbfd0da24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -161,6 +161,7 @@ dependencies = [ "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.16 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -178,6 +179,7 @@ dependencies = [ "tokio-process 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index efe1452357..df97bd2f06 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,3 +34,5 @@ tokio-io = "=0.1.10" tokio-process = "=0.2.3" tokio-threadpool = "=0.1.9" url = "=1.7.1" +kernel32-sys = "=0.2.2" +winapi = "=0.3.6" diff --git a/src/resources.rs b/src/resources.rs index 75612e574b..dd1ad00562 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -43,6 +43,18 @@ pub type ResourceId = u32; // Sometimes referred to RID. // system ones. type ResourceTable = HashMap; +#[cfg(not(windows))] +use std::os::unix::io::FromRawFd; + +#[cfg(windows)] +use std::os::windows::io::FromRawHandle; + +#[cfg(windows)] +extern crate kernel32; + +#[cfg(windows)] +extern crate winapi; + lazy_static! { // Starts at 3 because stdio is [0-2]. static ref NEXT_RID: AtomicUsize = AtomicUsize::new(3); @@ -50,7 +62,18 @@ lazy_static! { let mut m = HashMap::new(); // TODO Load these lazily during lookup? m.insert(0, Repr::Stdin(tokio::io::stdin())); - m.insert(1, Repr::Stdout(tokio::io::stdout())); + + m.insert(1, Repr::Stdout({ + #[cfg(not(windows))] + let stdout = unsafe { std::fs::File::from_raw_fd(1) }; + #[cfg(windows)] + let stdout = unsafe { + std::fs::File::from_raw_handle(kernel32::GetStdHandle( + winapi::um::winbase::STD_OUTPUT_HANDLE)) + }; + tokio::fs::File::from_std(stdout) + })); + m.insert(2, Repr::Stderr(tokio::io::stderr())); m }); @@ -59,7 +82,7 @@ lazy_static! { // Internal representation of Resource. enum Repr { Stdin(tokio::io::Stdin), - Stdout(tokio::io::Stdout), + Stdout(tokio::fs::File), Stderr(tokio::io::Stderr), FsFile(tokio::fs::File), TcpListener(tokio::net::TcpListener), diff --git a/tests/unbuffered_stderr.test b/tests/unbuffered_stderr.test new file mode 100644 index 0000000000..0e4109c7f6 --- /dev/null +++ b/tests/unbuffered_stderr.test @@ -0,0 +1,3 @@ +args: tests/unbuffered_stderr.ts --reload +check_stderr: true +output: tests/unbuffered_stderr.ts.out diff --git a/tests/unbuffered_stderr.ts b/tests/unbuffered_stderr.ts new file mode 100644 index 0000000000..df6b0ceb5d --- /dev/null +++ b/tests/unbuffered_stderr.ts @@ -0,0 +1,3 @@ +import { stderr } from "deno"; + +stderr.write(new TextEncoder().encode("x")); diff --git a/tests/unbuffered_stderr.ts.out b/tests/unbuffered_stderr.ts.out new file mode 100644 index 0000000000..66f8d4f59c --- /dev/null +++ b/tests/unbuffered_stderr.ts.out @@ -0,0 +1 @@ +[WILDCARD]x \ No newline at end of file diff --git a/tests/unbuffered_stdout.test b/tests/unbuffered_stdout.test new file mode 100644 index 0000000000..d0476b3ac1 --- /dev/null +++ b/tests/unbuffered_stdout.test @@ -0,0 +1,2 @@ +args: tests/unbuffered_stdout.ts --reload +output: tests/unbuffered_stdout.ts.out diff --git a/tests/unbuffered_stdout.ts b/tests/unbuffered_stdout.ts new file mode 100644 index 0000000000..9c2c2d7258 --- /dev/null +++ b/tests/unbuffered_stdout.ts @@ -0,0 +1,3 @@ +import { stdout } from "deno"; + +stdout.write(new TextEncoder().encode("a")); diff --git a/tests/unbuffered_stdout.ts.out b/tests/unbuffered_stdout.ts.out new file mode 100644 index 0000000000..2e65efe2a1 --- /dev/null +++ b/tests/unbuffered_stdout.ts.out @@ -0,0 +1 @@ +a \ No newline at end of file