Skip to content

Commit

Permalink
refactor!: get rid of the pidfile and find a better way to get the ru…
Browse files Browse the repository at this point in the history
…nning pid #48
  • Loading branch information
PlexSheep committed Jan 8, 2025
1 parent 716ad30 commit 295ea4f
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 96 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ tracing-subscriber = { version = "0.3.18", optional = true }
chrono = { version = "0.4.38", optional = false }
blake3 = "1.5.4"
serde_repr = "0.1.19"
sysinfo = "0.33.1"

[[bin]] # client
name = "netpulse"
Expand Down
57 changes: 19 additions & 38 deletions src/bins/netpulsed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use std::sync::atomic::AtomicBool;

use getopts::Options;
use netpulse::common::{
confirm, exec_cmd_for_user, getpid, getpid_running, init_logging, print_usage, root_guard,
confirm, exec_cmd_for_user, getpid_running, init_logging, print_usage, root_guard,
setup_panic_handler,
};
use netpulse::errors::RunError;
Expand All @@ -38,6 +38,7 @@ use netpulse::{DAEMON_PID_FILE, DAEMON_USER};
use nix::errno::Errno;
use nix::sys::signal::{self, Signal};
use nix::unistd::Pid;
use sysinfo::{Process, System};
use tracing::{debug, error, info, trace};

mod daemon;
Expand Down Expand Up @@ -144,35 +145,20 @@ fn setup_general(skip_checks: bool) -> Result<(), RunError> {
}

fn setup_systemd(skip_checks: bool) -> Result<(), RunError> {
let mut is_running: bool = getpid_running().is_some();
info!("netpulsed is running: {is_running}");
let mut stop_requested = false;

while is_running {
if !stop_requested && is_running {
println!("netpulsed.service needs to be stopped if it's running.");
println!(
"To stop the running netpulsed.service (using systemd), run the following as root:"
);
println!(" systemctl stop netpulsed.service");
if !confirm("Do this automatically now?") {
stop_requested = true;
continue;
}
exec_cmd_for_user(
Command::new("systemctl")
.arg("stop")
.arg("netpulsed.service"),
skip_checks,
);
stop_requested = true;
println!(
"waiting until netpulsed is no longer running (pid: {:?})",
getpid()
);
if let Some(pid) = getpid_running() {
let s = System::new_all();
info!("daemon runs with pid {pid}");
let process = s
.process(pid)
.expect("process for the pid of the daemon not found");
if !skip_checks || !confirm("terminate the daemon now?") {
println!("stopping setup");
std::process::exit(0);
}
is_running = getpid_running().is_some();
std::thread::sleep(std::time::Duration::from_millis(50));
process
.kill_with(sysinfo::Signal::Term)
.expect("SIGTERM does not exist on this platform");
process.wait(); // wait until the daemon has stopped
}

setup_general(skip_checks)?;
Expand Down Expand Up @@ -227,15 +213,9 @@ fn setup_systemd(skip_checks: bool) -> Result<(), RunError> {
}

fn infod() {
match getpid() {
match getpid_running() {
Some(pid) => {
if pid_runs(pid) {
println!("netpulsed is running with pid {pid}")
} else {
println!(
"the pid file exists with pid {pid}, but no process with that pid is running"
)
}
println!("netpulsed is running with pid {pid}")
}
None => println!("netpulsed is not running"),
}
Expand All @@ -253,7 +233,8 @@ fn endd() {
println!("netpulsed is not running");
return;
}
Some(raw) => Pid::from_raw(raw),
Some(raw) => Pid::from_raw(raw.as_u32() as i32), // this is weird, sysinfo has another raw type
// for pids than nix
};

match signal::kill(pid, Signal::SIGTERM) {
Expand Down
82 changes: 24 additions & 58 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,9 @@ use std::io::{self, Write as _};
use std::process::Command;
use std::str::FromStr;

use crate::DAEMON_PID_FILE;

use getopts::Options;
use tracing::{error, trace};
use sysinfo::{Pid, System};
use tracing::{debug, error, trace, warn};
use tracing_subscriber::FmtSubscriber;

/// Environment variable name for configuring log level
Expand Down Expand Up @@ -241,64 +240,31 @@ pub fn exec_cmd_for_user(cmd: &mut Command, skip_checks: bool) {
}
}

/// Checks if the netpulse daemon is currently running.
///
/// # Returns
///
/// * `Some(pid)` - Daemon is running with the given PID
/// * `None` - Daemon is not running
///
/// Checks both PID file existence and process existence.
pub fn getpid_running() -> Option<i32> {
getpid().filter(|p| pid_runs(*p))
}

/// Checks if a process with the given PID exists.
///
/// # Arguments
///
/// * `pid` - Process ID to check
///
/// # Returns
///
/// * `true` if process exists
/// * `false` if process does not exist
///
/// # Panics
///
/// Panics if unable to check process existence (e.g., permission denied)
pub fn pid_runs(pid: i32) -> bool {
std::fs::exists(format!("/proc/{pid}")).expect("could not check if the process exists")
}
/// Get the pid of the running netpulsed daemon
pub fn getpid_running() -> Option<Pid> {
let s = System::new_all();
let mut processes: Vec<&sysinfo::Process> =
s.processes_by_exact_name("netpulsed".as_ref()).collect();

/// Reads the daemon's PID from its PID file.
///
/// # Returns
///
/// * `Some(pid)` - Successfully read PID from file
/// * `None` - If PID file doesn't exist or contains invalid data
///
/// # Panics
///
/// Panics if:
/// - Unable to check PID file existence
/// - PID file exists but can't be read
pub fn getpid() -> Option<i32> {
if !std::fs::exists(DAEMON_PID_FILE).expect("couldn't check if the pid file exists") {
if processes.is_empty() {
None
} else if processes.len() == 1 {
Some(processes[0].pid())
} else {
let pid_raw = std::fs::read_to_string(DAEMON_PID_FILE)
.expect("pid file does not exist")
.trim()
.to_string();
let pid = match pid_raw.parse() {
Ok(pid) => pid,
Err(err) => {
error!("Error while parsing the pid from file ('{pid_raw}'): {err}");
return None;
}
};
Some(pid)
// FIXME: for some reason, this shows many processes even if only two are running.
// Expected:
// 1. the real daemon
// 2. this current process, which is also netpulsed
// BUT:
// For some absurd reason, there are 18 processes running
// Upstream Issue: https://github.com/GuillaumeGomez/sysinfo/issues/1449
warn!("netpulsed is running multiple times ({})", processes.len());
processes.sort_by_key(|a| a.pid());
debug!(
"listing netpulsed processes: {:?}",
processes.iter().map(|p| p.pid()).collect::<Vec<_>>()
);
Some(processes[0].pid())
}
}

Expand Down

0 comments on commit 295ea4f

Please sign in to comment.