diff --git a/src/builtins/disown.rs b/src/builtins/disown.rs index 5a38196ba..681377136 100644 --- a/src/builtins/disown.rs +++ b/src/builtins/disown.rs @@ -6,7 +6,7 @@ use crate::proc::{Job, add_disowned_job}; use crate::{builtins::shared::HelpOnlyCmdOpts, localization::wgettext_fmt}; use fish_widestring::wstr; -use libc::SIGCONT; +use nix::sys::signal::{Signal, killpg}; /// Helper for builtin_disown. fn disown_job(cmd: &wstr, streams: &mut IoStreams, j: &Job) { @@ -19,9 +19,7 @@ fn disown_job(cmd: &wstr, streams: &mut IoStreams, j: &Job) { let pgid = j.get_pgid(); if j.is_stopped() { if let Some(pgid) = pgid { - unsafe { - libc::killpg(pgid.as_pid_t(), SIGCONT); - } + let _ = killpg(pgid.as_nix_pid(), Some(Signal::SIGCONT)); } streams.err.append(&wgettext_fmt!( "%s: job %d ('%s') was stopped and has been signalled to continue.\n", diff --git a/src/proc.rs b/src/proc.rs index 9d9aa1b29..47ed17286 100644 --- a/src/proc.rs +++ b/src/proc.rs @@ -3,9 +3,7 @@ //! the exec library will call proc to create representations of the running jobs as needed. use crate::ast; -use crate::common::{ - Timepoint, WSL, charptr2wcstring, escape, is_windows_subsystem_for_linux, timef, -}; +use crate::common::{Timepoint, WSL, escape, is_windows_subsystem_for_linux, timef}; use crate::env::Statuses; use crate::event::{self, Event}; use crate::flog::{flog, flogf}; @@ -25,13 +23,13 @@ use cfg_if::cfg_if; use fish_widestring::ToWString; use libc::{ - _SC_CLK_TCK, EXIT_SUCCESS, SIG_IGN, SIGABRT, SIGBUS, SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT, - SIGKILL, SIGPIPE, SIGQUIT, SIGSEGV, SIGSYS, SIGTTOU, STDOUT_FILENO, WCONTINUED, WEXITSTATUS, - WIFCONTINUED, WIFEXITED, WIFSIGNALED, WIFSTOPPED, WNOHANG, WTERMSIG, WUNTRACED, + _SC_CLK_TCK, EXIT_SUCCESS, SIG_IGN, SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGINT, SIGPIPE, SIGQUIT, + SIGSEGV, SIGSYS, SIGTTOU, STDOUT_FILENO, WCONTINUED, WEXITSTATUS, WIFCONTINUED, WIFEXITED, + WIFSIGNALED, WIFSTOPPED, WNOHANG, WTERMSIG, WUNTRACED, }; use nix::{ sys::{ - signal::{SaFlags, SigAction, SigHandler, SigSet}, + signal::{SaFlags, SigAction, SigHandler, SigSet, Signal as NixSignal, kill, killpg}, wait::{WaitPidFlag, WaitStatus, waitpid}, }, unistd::getpgrp, @@ -835,7 +833,7 @@ pub fn continue_job(&self, parser: &Parser, block_io: Option<&IoChain>) { /// Return true on success, false if we failed to send the signal. pub fn resume(&self) -> bool { self.mut_flags().notified_of_stop = false; - if !self.signal(SIGCONT) { + if !self.signal(NixSignal::SIGCONT) { flogf!( proc_pgroup, "Failed to send SIGCONT to procs in job %s", @@ -853,24 +851,17 @@ pub fn resume(&self) -> bool { /// Send the specified signal to all processes in this job. /// Return true on success, false on failure. - pub fn signal(&self, signal: i32) -> bool { + pub fn signal(&self, signal: NixSignal) -> bool { if let Some(pgid) = self.group().get_pgid() { - if unsafe { libc::killpg(pgid.as_pid_t(), signal) } == -1 { - let strsignal = unsafe { libc::strsignal(signal) }; - let strsignal = if strsignal.is_null() { - L!("(nil)").to_owned() - } else { - charptr2wcstring(strsignal) - }; + if killpg(pgid.as_nix_pid(), signal).is_err() { + let strsignal = signal.as_str(); wperror(&sprintf!("killpg(%d, %s)", pgid, strsignal)); return false; } } else { // This job lives in fish's pgroup and we need to signal procs individually. for p in self.external_procs() { - if !p.is_completed() - && unsafe { libc::kill(p.pid().unwrap().as_pid_t(), signal) } == -1 - { + if !p.is_completed() && kill(p.pid().unwrap().as_nix_pid(), signal).is_err() { return false; } } @@ -1123,9 +1114,9 @@ pub fn hup_jobs(jobs: &JobList) { for j in jobs { let Some(pgid) = j.get_pgid() else { continue }; if pgid.as_nix_pid() != fish_pgrp && !j.is_completed() { - j.signal(SIGHUP); + j.signal(NixSignal::SIGHUP); if j.is_stopped() { - j.signal(SIGCONT); + j.signal(NixSignal::SIGCONT); } // For most applications, the above alone is sufficient for the suspended process to @@ -1149,7 +1140,7 @@ pub fn hup_jobs(jobs: &JobList) { // handle SIGHUP+SIGCONT without running into SIGTTOU. std::thread::sleep(std::time::Duration::from_millis(50)); for j in kill_list.drain(..) { - j.signal(SIGKILL); + j.signal(NixSignal::SIGKILL); } } } diff --git a/src/reader/reader.rs b/src/reader/reader.rs index 3499d7fc7..c42ad608b 100644 --- a/src/reader/reader.rs +++ b/src/reader/reader.rs @@ -17,37 +17,6 @@ //! control-C from generating SIGINT, so failing to disable these would prevent cancellation of wildcard //! expansion, etc. -use crate::portable_atomic::AtomicU64; -use fish_common::{UTF8_BOM_WCHAR, help_section}; -use fish_fallback::lowercase; -use fish_wcstringutil::{IsPrefix, is_prefix}; -use libc::{ - _POSIX_VDISABLE, ECHO, EINTR, EIO, EISDIR, ENOTTY, EPERM, ESRCH, FLUSHO, ICANON, ICRNL, IEXTEN, - INLCR, IXOFF, IXON, O_NONBLOCK, O_RDONLY, ONLCR, OPOST, SIGINT, SIGTTIN, STDERR_FILENO, - STDIN_FILENO, STDOUT_FILENO, TCSANOW, VMIN, VQUIT, VSUSP, VTIME, c_char, -}; -use nix::fcntl::OFlag; -use nix::sys::stat::Mode; -use nix::unistd::getpgrp; -use std::borrow::Cow; -use std::cell::UnsafeCell; -use std::cmp; -use std::io::BufReader; -use std::mem::MaybeUninit; -use std::num::NonZeroUsize; -use std::ops::ControlFlow; -use std::ops::Range; -use std::os::fd::BorrowedFd; -use std::os::fd::FromRawFd; -use std::os::fd::OwnedFd; -use std::os::fd::{AsRawFd, RawFd}; -use std::pin::Pin; -use std::sync::atomic::{AtomicI32, AtomicU8, AtomicU32, Ordering}; -use std::sync::{Arc, LazyLock, Mutex, MutexGuard, OnceLock}; -use std::time::{Duration, Instant}; - -use errno::{Errno, errno}; - use super::history_search::{ReaderHistorySearch, SearchMode, smartcase_flags}; use super::iothreads::{self, Debouncers}; use super::word_motion::{MoveWordDir, MoveWordStateMachine, MoveWordStyle}; @@ -112,6 +81,7 @@ get_token_extent, lineno, locate_cmdsubst_range, }; use crate::parser::{BlockType, EvalRes, Parser, ParserEnvSetMode}; +use crate::portable_atomic::AtomicU64; use crate::prelude::*; use crate::proc::{ HAVE_PROC_STAT, hup_jobs, is_interactive_session, job_reap, jobs_requiring_warning_on_exit, @@ -146,12 +116,45 @@ use crate::wutil::{fstat, perror, write_to_fd, wstat}; use crate::{abbrs, event, function}; use assert_matches::assert_matches; +use errno::{Errno, errno}; +use fish_common::{UTF8_BOM_WCHAR, help_section}; use fish_fallback::fish_wcwidth; +use fish_fallback::lowercase; use fish_wcstringutil::{ CaseSensitivity, StringFuzzyMatch, count_preceding_backslashes, join_strings, string_prefixes_string, string_prefixes_string_case_insensitive, string_prefixes_string_maybe_case_insensitive, }; +use fish_wcstringutil::{IsPrefix, is_prefix}; +use libc::{ + _POSIX_VDISABLE, ECHO, EINTR, EIO, EISDIR, ENOTTY, EPERM, ESRCH, FLUSHO, ICANON, ICRNL, IEXTEN, + INLCR, IXOFF, IXON, O_NONBLOCK, O_RDONLY, ONLCR, OPOST, SIGINT, STDERR_FILENO, STDIN_FILENO, + STDOUT_FILENO, TCSANOW, VMIN, VQUIT, VSUSP, VTIME, c_char, +}; +use nix::{ + fcntl::OFlag, + sys::{ + signal::{Signal, killpg}, + stat::Mode, + }, + unistd::getpgrp, +}; +use std::{ + borrow::Cow, + cell::UnsafeCell, + cmp, + io::BufReader, + mem::MaybeUninit, + num::NonZeroUsize, + ops::{ControlFlow, Range}, + os::fd::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd}, + pin::Pin, + sync::{ + Arc, LazyLock, Mutex, MutexGuard, OnceLock, + atomic::{AtomicI32, AtomicU8, AtomicU32, Ordering}, + }, + time::{Duration, Instant}, +}; /// A description of where fish is in the process of exiting. #[repr(u8)] @@ -4921,8 +4924,7 @@ fn acquire_tty_or_exit(shell_pgid: libc::pid_t) { } // Try stopping us. - let ret = unsafe { libc::killpg(shell_pgid, SIGTTIN) }; - if ret < 0 { + if killpg(nix::unistd::Pid::from_raw(shell_pgid), Signal::SIGTTIN).is_err() { perror("killpg(shell_pgid, SIGTTIN)"); exit_without_destructors(1); }