diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2022-07-13 11:16:42 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-13 11:16:42 -0400 |
commit | 667812a297a538863695c20bf5d8228301298db5 (patch) | |
tree | d6f884ee4f0102831283f077ffd5d797a9eada5e /runtime/ops/tty.rs | |
parent | 7470b2d2a765396a283bfd169b5fa9bacf0c01d0 (diff) |
fix(cli): synchronize async stdio/file reads and writes (#15092)
Fixes a regression where async writes and reads could get out of order.
Diffstat (limited to 'runtime/ops/tty.rs')
-rw-r--r-- | runtime/ops/tty.rs | 131 |
1 files changed, 67 insertions, 64 deletions
diff --git a/runtime/ops/tty.rs b/runtime/ops/tty.rs index 62a7717a6..ab9553025 100644 --- a/runtime/ops/tty.rs +++ b/runtime/ops/tty.rs @@ -82,82 +82,85 @@ fn op_set_raw(state: &mut OpState, args: SetRawArgs) -> Result<(), AnyError> { use winapi::shared::minwindef::FALSE; use winapi::um::{consoleapi, handleapi}; - let resource = state.resource_table.get::<StdFileResource>(rid)?; - if cbreak { return Err(deno_core::error::not_supported()); } - let std_file = resource.std_file(); - let std_file = std_file.lock(); // hold the lock - let handle = std_file.as_raw_handle(); + StdFileResource::with_file(state, rid, move |std_file| { + let handle = std_file.as_raw_handle(); - if handle == handleapi::INVALID_HANDLE_VALUE { - return Err(Error::last_os_error().into()); - } else if handle.is_null() { - return Err(custom_error("ReferenceError", "null handle")); - } - let mut original_mode: DWORD = 0; - if unsafe { consoleapi::GetConsoleMode(handle, &mut original_mode) } - == FALSE - { - return Err(Error::last_os_error().into()); - } - let new_mode = if is_raw { - original_mode & !RAW_MODE_MASK - } else { - original_mode | RAW_MODE_MASK - }; - if unsafe { consoleapi::SetConsoleMode(handle, new_mode) } == FALSE { - return Err(Error::last_os_error().into()); - } + if handle == handleapi::INVALID_HANDLE_VALUE { + return Err(Error::last_os_error().into()); + } else if handle.is_null() { + return Err(custom_error("ReferenceError", "null handle")); + } + let mut original_mode: DWORD = 0; + if unsafe { consoleapi::GetConsoleMode(handle, &mut original_mode) } + == FALSE + { + return Err(Error::last_os_error().into()); + } + let new_mode = if is_raw { + original_mode & !RAW_MODE_MASK + } else { + original_mode | RAW_MODE_MASK + }; + if unsafe { consoleapi::SetConsoleMode(handle, new_mode) } == FALSE { + return Err(Error::last_os_error().into()); + } - Ok(()) + Ok(()) + }) } #[cfg(unix)] { use std::os::unix::io::AsRawFd; - let resource = state.resource_table.get::<StdFileResource>(rid)?; - let std_file = resource.std_file(); - let raw_fd = std_file.lock().as_raw_fd(); - let mut meta_data = resource.metadata_mut(); - let maybe_tty_mode = &mut meta_data.tty.mode; - - if is_raw { - if maybe_tty_mode.is_none() { - // Save original mode. - let original_mode = termios::tcgetattr(raw_fd)?; - maybe_tty_mode.replace(original_mode); - } - - let mut raw = maybe_tty_mode.clone().unwrap(); - - raw.input_flags &= !(termios::InputFlags::BRKINT - | termios::InputFlags::ICRNL - | termios::InputFlags::INPCK - | termios::InputFlags::ISTRIP - | termios::InputFlags::IXON); - - raw.control_flags |= termios::ControlFlags::CS8; - - raw.local_flags &= !(termios::LocalFlags::ECHO - | termios::LocalFlags::ICANON - | termios::LocalFlags::IEXTEN); - if !cbreak { - raw.local_flags &= !(termios::LocalFlags::ISIG); - } - raw.control_chars[termios::SpecialCharacterIndices::VMIN as usize] = 1; - raw.control_chars[termios::SpecialCharacterIndices::VTIME as usize] = 0; - termios::tcsetattr(raw_fd, termios::SetArg::TCSADRAIN, &raw)?; - } else { - // Try restore saved mode. - if let Some(mode) = maybe_tty_mode.take() { - termios::tcsetattr(raw_fd, termios::SetArg::TCSADRAIN, &mode)?; - } - } + StdFileResource::with_file_and_metadata( + state, + rid, + move |std_file, meta_data| { + let raw_fd = std_file.as_raw_fd(); + let maybe_tty_mode = &mut meta_data.tty.mode; + + if is_raw { + if maybe_tty_mode.is_none() { + // Save original mode. + let original_mode = termios::tcgetattr(raw_fd)?; + maybe_tty_mode.replace(original_mode); + } + + let mut raw = maybe_tty_mode.clone().unwrap(); + + raw.input_flags &= !(termios::InputFlags::BRKINT + | termios::InputFlags::ICRNL + | termios::InputFlags::INPCK + | termios::InputFlags::ISTRIP + | termios::InputFlags::IXON); + + raw.control_flags |= termios::ControlFlags::CS8; + + raw.local_flags &= !(termios::LocalFlags::ECHO + | termios::LocalFlags::ICANON + | termios::LocalFlags::IEXTEN); + if !cbreak { + raw.local_flags &= !(termios::LocalFlags::ISIG); + } + raw.control_chars[termios::SpecialCharacterIndices::VMIN as usize] = + 1; + raw.control_chars[termios::SpecialCharacterIndices::VTIME as usize] = + 0; + termios::tcsetattr(raw_fd, termios::SetArg::TCSADRAIN, &raw)?; + } else { + // Try restore saved mode. + if let Some(mode) = maybe_tty_mode.take() { + termios::tcsetattr(raw_fd, termios::SetArg::TCSADRAIN, &mode)?; + } + } - Ok(()) + Ok(()) + }, + ) } } |