From c23d8e830ad1eb7aab4966ece9484eb8a9e7b12f Mon Sep 17 00:00:00 2001 From: Thomas Otto Date: Mon, 22 Jul 2024 23:41:51 +0200 Subject: [PATCH] Set calling process directly because delta started it This info then takes precedence over whatever start_determining_calling_process_in_thread() finds or rather doesn't find. (The simple yet generous SeqCst is used on purpose for the atomic operations.) --- src/main.rs | 11 ++++++++++- src/utils/mod.rs | 4 ++++ src/utils/process.rs | 31 +++++++++++++++++++++++++++++-- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index a2a0ed857..2c85daacc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,7 @@ mod subcommands; mod tests; -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; use std::io::{self, BufRead, Cursor, ErrorKind, IsTerminal, Write}; use std::process::{self, Command, Stdio}; @@ -91,6 +91,15 @@ pub fn run_app( } else if let Call::Help(msg) = call { OutputType::oneshot_write(msg)?; return Ok(0); + } else if let Call::SubCommand(_, cmd) = &call { + // Set before creating the Config, which already asks for the calling process + // (not required for Call::DeltaDiff) + utils::process::set_calling_process( + &cmd.args + .iter() + .map(|arg| OsStr::to_string_lossy(arg).to_string()) + .collect::>(), + ); } let opt = opt.unwrap_or_else(|| delta_unreachable("Opt is set")); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index b460e5af3..2841fcb93 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -9,3 +9,7 @@ pub mod round_char_boundary; pub mod syntect; pub mod tabs; pub mod workarounds; + +// Use the most (even overly) strict ordering. Atomics are not used in hot loops so +// a one-size-fits-all approach which is never incorrect is okay. +pub const DELTA_ATOMIC_ORDERING: std::sync::atomic::Ordering = std::sync::atomic::Ordering::SeqCst; diff --git a/src/utils/process.rs b/src/utils/process.rs index f1e3c665d..5dd08cb88 100644 --- a/src/utils/process.rs +++ b/src/utils/process.rs @@ -1,10 +1,13 @@ use std::collections::{HashMap, HashSet}; use std::path::Path; +use std::sync::atomic::AtomicUsize; use std::sync::{Arc, Condvar, Mutex, MutexGuard}; use lazy_static::lazy_static; use sysinfo::{Pid, PidExt, Process, ProcessExt, ProcessRefreshKind, SystemExt}; +use crate::utils::DELTA_ATOMIC_ORDERING; + pub type DeltaPid = u32; #[derive(Clone, Debug, PartialEq, Eq)] @@ -19,7 +22,13 @@ pub enum CallingProcess { None, // no matching process could be found Pending, // calling process is currently being determined } -// TODO: Git blame is currently handled differently + +// The information where the calling process info comes from *should* be inside +// `CallingProcess`, but that is handed out (within a MutexGuard) to callers. +// To keep the interface simple, store it here: +static CALLER_INFO_SOURCE: AtomicUsize = AtomicUsize::new(CALLER_GUESSED); +const CALLER_GUESSED: usize = 1; +const CALLER_KNOWN: usize = 2; impl CallingProcess { pub fn paths_in_input_are_relative_to_cwd(&self) -> bool { @@ -47,6 +56,8 @@ lazy_static! { Arc::new((Mutex::new(CallingProcess::Pending), Condvar::new())); } +// delta was called by this process (or called by something which called delta and it), +// try looking up this information in the process tree. pub fn start_determining_calling_process_in_thread() { // The handle is neither kept nor returned nor joined but dropped, so the main // thread can exit early if it does not need to know its parent process. @@ -58,12 +69,28 @@ pub fn start_determining_calling_process_in_thread() { let (caller_mutex, determine_done) = &**CALLER; let mut caller = caller_mutex.lock().unwrap(); - *caller = calling_process; + + if CALLER_INFO_SOURCE.load(DELTA_ATOMIC_ORDERING) <= CALLER_GUESSED { + *caller = calling_process; + } + determine_done.notify_all(); }) .unwrap(); } +// delta starts the process, so it is known. +pub fn set_calling_process(args: &[String]) { + if let ProcessArgs::Args(result) = describe_calling_process(args) { + let (caller_mutex, determine_done) = &**CALLER; + + let mut caller = caller_mutex.lock().unwrap(); + *caller = result; + CALLER_INFO_SOURCE.store(CALLER_KNOWN, DELTA_ATOMIC_ORDERING); + determine_done.notify_all(); + } +} + #[cfg(not(test))] pub fn calling_process() -> MutexGuard<'static, CallingProcess> { let (caller_mutex, determine_done) = &**CALLER;