1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-24 15:19:26 -05:00

fix(repl): Prevent panic on broken pipe (#21945)

This commit is contained in:
melbourne2991 2024-08-20 10:21:12 +10:00 committed by GitHub
parent 1c4db2aca9
commit 0eba180fdb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 43 additions and 5 deletions

View file

@ -1,5 +1,8 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use std::io;
use std::io::Write;
use std::sync::Arc; use std::sync::Arc;
use crate::args::CliOptions; use crate::args::CliOptions;
@ -241,15 +244,24 @@ pub async fn run(
// Doing this manually, instead of using `log::info!` because these messages // Doing this manually, instead of using `log::info!` because these messages
// are supposed to go to stdout, not stderr. // are supposed to go to stdout, not stderr.
// Using writeln, because println panics in certain cases
// (eg: broken pipes - https://github.com/denoland/deno/issues/21861)
if !cli_options.is_quiet() { if !cli_options.is_quiet() {
println!("Deno {}", crate::version::DENO_VERSION_INFO.deno); let mut handle = io::stdout().lock();
println!("exit using ctrl+d, ctrl+c, or close()");
writeln!(handle, "Deno {}", crate::version::DENO_VERSION_INFO.deno)?;
writeln!(handle, "exit using ctrl+d, ctrl+c, or close()")?;
if repl_flags.is_default_command { if repl_flags.is_default_command {
println!( writeln!(
handle,
"{}", "{}",
colors::yellow("REPL is running with all permissions allowed.") colors::yellow("REPL is running with all permissions allowed.")
); )?;
println!("To specify permissions, run `deno repl` with allow flags.") writeln!(
handle,
"To specify permissions, run `deno repl` with allow flags."
)?;
} }
} }

View file

@ -4343,6 +4343,32 @@ fn broken_stdout() {
assert!(!stderr.contains("panic")); assert!(!stderr.contains("panic"));
} }
#[test]
fn broken_stdout_repl() {
let (reader, writer) = os_pipe::pipe().unwrap();
// drop the reader to create a broken pipe
drop(reader);
let output = util::deno_cmd()
.current_dir(util::testdata_path())
.arg("repl")
.stdout(writer)
.stderr_piped()
.spawn()
.unwrap()
.wait_with_output()
.unwrap();
assert!(!output.status.success());
let stderr = std::str::from_utf8(output.stderr.as_ref()).unwrap().trim();
if cfg!(windows) {
assert_contains!(stderr, "The pipe is being closed. (os error 232)");
} else {
assert_contains!(stderr, "Broken pipe (os error 32)");
}
assert_not_contains!(stderr, "panic");
}
itest!(error_cause { itest!(error_cause {
args: "run run/error_cause.ts", args: "run run/error_cause.ts",
output: "run/error_cause.ts.out", output: "run/error_cause.ts.out",