Clarify threading semantics of DISOWNED_PIDS

While obtaining an uncontested mutex from the same thread (without reentrance)
is basically ~free, the use of `MainThread<RefCell<T>>` instead of `Mutex<T>`
makes it clear that there is no actual synchronization taking place, hopefully
making the code easier to understand.
This commit is contained in:
Mahmoud Al-Qudsi 2024-05-24 10:13:04 -05:00
parent 43d6289c26
commit 59317da19e

View File

@ -18,6 +18,7 @@ use crate::parser::{Block, Parser};
use crate::reader::{fish_is_unwinding_for_exit, reader_schedule_prompt_repaint};
use crate::redirection::RedirectionSpecList;
use crate::signal::{signal_set_handlers_once, Signal};
use crate::threads::MainThread;
use crate::topic_monitor::{topic_monitor_principal, topic_t, GenerationsList};
use crate::wait_handle::{InternalJobId, WaitHandle, WaitHandleRef, WaitHandleStore};
use crate::wchar::{wstr, WString, L};
@ -37,7 +38,7 @@ use std::io::{Read, Write};
use std::os::fd::RawFd;
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, AtomicI32, AtomicU64, AtomicU8, Ordering};
use std::sync::{Arc, Mutex};
use std::sync::Arc;
/// Types of processes.
#[derive(Default, Eq, PartialEq)]
@ -1309,7 +1310,7 @@ pub fn hup_jobs(jobs: &JobList) {
/// Add a job to the list of PIDs/PGIDs we wait on even though they are not associated with any
/// jobs. Used to avoid zombie processes after disown.
pub fn add_disowned_job(j: &Job) {
let mut disowned_pids = DISOWNED_PIDS.lock().unwrap();
let mut disowned_pids = DISOWNED_PIDS.get().borrow_mut();
for process in j.processes().iter() {
if process.has_pid() {
disowned_pids.push(process.pid());
@ -1319,7 +1320,7 @@ pub fn add_disowned_job(j: &Job) {
// Reap any pids in our disowned list that have exited. This is used to avoid zombies.
fn reap_disowned_pids() {
let mut disowned_pids = DISOWNED_PIDS.lock().unwrap();
let mut disowned_pids = DISOWNED_PIDS.get().borrow_mut();
// waitpid returns 0 iff the PID/PGID in question has not changed state; remove the pid/pgid
// if it has changed or an error occurs (presumably ECHILD because the child does not exist)
disowned_pids.retain(|pid| {
@ -1334,7 +1335,8 @@ fn reap_disowned_pids() {
/// A list of pids that have been disowned. They are kept around until either they exit or
/// we exit. Poll these from time-to-time to prevent zombie processes from happening (#5342).
static DISOWNED_PIDS: Mutex<Vec<libc::pid_t>> = Mutex::new(Vec::new());
static DISOWNED_PIDS: MainThread<RefCell<Vec<libc::pid_t>>> =
MainThread::new(RefCell::new(Vec::new()));
/// See if any reapable processes have exited, and mark them accordingly.
/// \param block_ok if no reapable processes have exited, block until one is (or until we receive a