mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Avoid potential contention on SIGTERM while enabling terminal protocols
We no longer use RAII for enabling/disabling these, so a full object is overkill. Additionally this object doesn't allow us to recover from the case where we receive SIGTERM while inside terminal_protocols_{enable,disable}. We can simply run disable another time since they're idempotent. Untested.
This commit is contained in:
parent
a7abd83c57
commit
37c04745e6
2 changed files with 57 additions and 76 deletions
|
@ -12,17 +12,16 @@ use crate::key::{
|
||||||
Key, Modifiers,
|
Key, Modifiers,
|
||||||
};
|
};
|
||||||
use crate::reader::{reader_current_data, reader_test_and_clear_interrupted};
|
use crate::reader::{reader_current_data, reader_test_and_clear_interrupted};
|
||||||
use crate::threads::{iothread_port, MainThread};
|
use crate::threads::iothread_port;
|
||||||
use crate::universal_notifier::default_notifier;
|
use crate::universal_notifier::default_notifier;
|
||||||
use crate::wchar::{encode_byte_to_char, prelude::*};
|
use crate::wchar::{encode_byte_to_char, prelude::*};
|
||||||
use crate::wutil::encoding::{mbrtowc, mbstate_t, zero_mbstate};
|
use crate::wutil::encoding::{mbrtowc, mbstate_t, zero_mbstate};
|
||||||
use crate::wutil::{fish_wcstol, write_to_fd};
|
use crate::wutil::{fish_wcstol, write_to_fd};
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
use std::os::fd::RawFd;
|
use std::os::fd::RawFd;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
|
|
||||||
// The range of key codes for inputrc-style keyboard functions.
|
// The range of key codes for inputrc-style keyboard functions.
|
||||||
pub const R_END_INPUT_FUNCTIONS: usize = (ReadlineCmd::ReverseRepeatJump as usize) + 1;
|
pub const R_END_INPUT_FUNCTIONS: usize = (ReadlineCmd::ReverseRepeatJump as usize) + 1;
|
||||||
|
@ -426,8 +425,7 @@ pub fn update_wait_on_sequence_key_ms(vars: &EnvStack) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static TERMINAL_PROTOCOLS: MainThread<RefCell<Option<TerminalProtocols>>> =
|
static TERMINAL_PROTOCOLS: AtomicBool = AtomicBool::new(false);
|
||||||
MainThread::new(RefCell::new(None));
|
|
||||||
|
|
||||||
pub(crate) static IS_TMUX: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
pub(crate) static IS_TMUX: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||||
pub(crate) static IN_MIDNIGHT_COMMANDER: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
pub(crate) static IN_MIDNIGHT_COMMANDER: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||||
|
@ -438,82 +436,65 @@ pub fn terminal_protocols_enable_ifn() {
|
||||||
if IN_MIDNIGHT_COMMANDER.load() {
|
if IN_MIDNIGHT_COMMANDER.load() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut term_protocols = TERMINAL_PROTOCOLS.get().borrow_mut();
|
if TERMINAL_PROTOCOLS.load(Ordering::Relaxed) {
|
||||||
if term_protocols.is_some() {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*term_protocols = Some(TerminalProtocols::new());
|
TERMINAL_PROTOCOLS.store(true, Ordering::Release);
|
||||||
|
let sequences = if IN_WEZTERM.load() {
|
||||||
|
"\x1b[?2004h"
|
||||||
|
} else if IN_ITERM_PRE_CSI_U.load() {
|
||||||
|
concat!("\x1b[?2004h", "\x1b[>4;1m", "\x1b[>5u", "\x1b=",)
|
||||||
|
} else {
|
||||||
|
concat!(
|
||||||
|
"\x1b[?2004h", // Bracketed paste
|
||||||
|
"\x1b[>4;1m", // XTerm's modifyOtherKeys
|
||||||
|
"\x1b[=5u", // CSI u with kitty progressive enhancement
|
||||||
|
"\x1b=", // set application keypad mode, so the keypad keys send unique codes
|
||||||
|
)
|
||||||
|
};
|
||||||
|
FLOG!(
|
||||||
|
term_protocols,
|
||||||
|
format!(
|
||||||
|
"Enabling extended keys and bracketed paste: {:?}",
|
||||||
|
sequences
|
||||||
|
)
|
||||||
|
);
|
||||||
|
let _ = write_to_fd(sequences.as_bytes(), STDOUT_FILENO);
|
||||||
|
if IS_TMUX.load() {
|
||||||
|
let _ = write_to_fd("\x1b[?1004h".as_bytes(), STDOUT_FILENO);
|
||||||
|
}
|
||||||
|
reader_current_data().map(|data| data.save_screen_state());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn terminal_protocols_disable_ifn() {
|
pub(crate) fn terminal_protocols_disable_ifn() {
|
||||||
TERMINAL_PROTOCOLS.get().replace(None);
|
if !TERMINAL_PROTOCOLS.load(Ordering::Acquire) {
|
||||||
}
|
return;
|
||||||
|
|
||||||
pub(crate) fn terminal_protocols_try_disable_ifn() {
|
|
||||||
if let Ok(mut term_protocols) = TERMINAL_PROTOCOLS.get().try_borrow_mut() {
|
|
||||||
*term_protocols = None;
|
|
||||||
}
|
}
|
||||||
}
|
let sequences = if IN_WEZTERM.load() {
|
||||||
|
"\x1b[?2004l"
|
||||||
struct TerminalProtocols {}
|
} else if IN_ITERM_PRE_CSI_U.load() {
|
||||||
|
concat!("\x1b[?2004l", "\x1b[>4;0m", "\x1b[<1u", "\x1b>",)
|
||||||
impl TerminalProtocols {
|
} else {
|
||||||
fn new() -> Self {
|
concat!(
|
||||||
let sequences = if IN_WEZTERM.load() {
|
"\x1b[?2004l", // Bracketed paste
|
||||||
"\x1b[?2004h"
|
"\x1b[>4;0m", // XTerm's modifyOtherKeys
|
||||||
} else if IN_ITERM_PRE_CSI_U.load() {
|
"\x1b[=0u", // CSI u with kitty progressive enhancement
|
||||||
concat!("\x1b[?2004h", "\x1b[>4;1m", "\x1b[>5u", "\x1b=",)
|
"\x1b>", // application keypad mode
|
||||||
} else {
|
)
|
||||||
concat!(
|
};
|
||||||
"\x1b[?2004h", // Bracketed paste
|
FLOG!(
|
||||||
"\x1b[>4;1m", // XTerm's modifyOtherKeys
|
term_protocols,
|
||||||
"\x1b[=5u", // CSI u with kitty progressive enhancement
|
format!(
|
||||||
"\x1b=", // set application keypad mode, so the keypad keys send unique codes
|
"Disabling extended keys and bracketed paste: {:?}",
|
||||||
)
|
sequences
|
||||||
};
|
)
|
||||||
FLOG!(
|
);
|
||||||
term_protocols,
|
let _ = write_to_fd(sequences.as_bytes(), STDOUT_FILENO);
|
||||||
format!(
|
if IS_TMUX.load() {
|
||||||
"Enabling extended keys and bracketed paste: {:?}",
|
let _ = write_to_fd("\x1b[?1004l".as_bytes(), STDOUT_FILENO);
|
||||||
sequences
|
|
||||||
)
|
|
||||||
);
|
|
||||||
let _ = write_to_fd(sequences.as_bytes(), STDOUT_FILENO);
|
|
||||||
if IS_TMUX.load() {
|
|
||||||
let _ = write_to_fd("\x1b[?1004h".as_bytes(), STDOUT_FILENO);
|
|
||||||
}
|
|
||||||
reader_current_data().map(|data| data.save_screen_state());
|
|
||||||
Self {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for TerminalProtocols {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
let sequences = if IN_WEZTERM.load() {
|
|
||||||
"\x1b[?2004l"
|
|
||||||
} else if IN_ITERM_PRE_CSI_U.load() {
|
|
||||||
concat!("\x1b[?2004l", "\x1b[>4;0m", "\x1b[<1u", "\x1b>",)
|
|
||||||
} else {
|
|
||||||
concat!(
|
|
||||||
"\x1b[?2004l", // Bracketed paste
|
|
||||||
"\x1b[>4;0m", // XTerm's modifyOtherKeys
|
|
||||||
"\x1b[=0u", // CSI u with kitty progressive enhancement
|
|
||||||
"\x1b>", // application keypad mode
|
|
||||||
)
|
|
||||||
};
|
|
||||||
FLOG!(
|
|
||||||
term_protocols,
|
|
||||||
format!(
|
|
||||||
"Disabling extended keys and bracketed paste: {:?}",
|
|
||||||
sequences
|
|
||||||
)
|
|
||||||
);
|
|
||||||
let _ = write_to_fd(sequences.as_bytes(), STDOUT_FILENO);
|
|
||||||
if IS_TMUX.load() {
|
|
||||||
let _ = write_to_fd("\x1b[?1004l".as_bytes(), STDOUT_FILENO);
|
|
||||||
}
|
|
||||||
reader_current_data().map(|data| data.save_screen_state());
|
|
||||||
}
|
}
|
||||||
|
reader_current_data().map(|data| data.save_screen_state());
|
||||||
|
TERMINAL_PROTOCOLS.store(false, Ordering::Release);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_mask(mask: u32) -> Modifiers {
|
fn parse_mask(mask: u32) -> Modifiers {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::num::NonZeroI32;
|
||||||
|
|
||||||
use crate::common::{exit_without_destructors, restore_term_foreground_process_group_for_exit};
|
use crate::common::{exit_without_destructors, restore_term_foreground_process_group_for_exit};
|
||||||
use crate::event::{enqueue_signal, is_signal_observed};
|
use crate::event::{enqueue_signal, is_signal_observed};
|
||||||
use crate::input_common::terminal_protocols_try_disable_ifn;
|
use crate::input_common::terminal_protocols_disable_ifn;
|
||||||
use crate::nix::getpid;
|
use crate::nix::getpid;
|
||||||
use crate::reader::{reader_handle_sigint, reader_sighup};
|
use crate::reader::{reader_handle_sigint, reader_sighup};
|
||||||
use crate::termsize::TermsizeContainer;
|
use crate::termsize::TermsizeContainer;
|
||||||
|
@ -89,7 +89,7 @@ extern "C" fn fish_signal_handler(
|
||||||
// Handle sigterm. The only thing we do is restore the front process ID, then die.
|
// Handle sigterm. The only thing we do is restore the front process ID, then die.
|
||||||
if !observed {
|
if !observed {
|
||||||
restore_term_foreground_process_group_for_exit();
|
restore_term_foreground_process_group_for_exit();
|
||||||
terminal_protocols_try_disable_ifn();
|
terminal_protocols_disable_ifn();
|
||||||
// Safety: signal() and raise() are async-signal-safe.
|
// Safety: signal() and raise() are async-signal-safe.
|
||||||
unsafe {
|
unsafe {
|
||||||
libc::signal(libc::SIGTERM, libc::SIG_DFL);
|
libc::signal(libc::SIGTERM, libc::SIG_DFL);
|
||||||
|
|
Loading…
Reference in a new issue