use std::fs;
use std::process::{Command, Stdio};
use crate::runtime::error::{Result, RuntimeError};
use crate::runtime::paths::RuntimePaths;
pub(crate) fn spawn_daemon(paths: &RuntimePaths) -> Result<u32> {
use std::os::unix::process::CommandExt;
fs::create_dir_all(&paths.runtime_dir)?;
fs::create_dir_all(&paths.log_dir)?;
let stdout = fs::File::create(paths.log_dir.join("bitrouter.out.log"))?;
let stderr = fs::File::create(paths.log_dir.join("bitrouter.err.log"))?;
let exe = std::env::current_exe()?;
let child = Command::new(exe)
.arg("--home-dir")
.arg(&paths.home_dir)
.arg("serve")
.stdout(stdout)
.stderr(stderr)
.stdin(Stdio::null())
.process_group(0)
.spawn()?;
Ok(child.id())
}
pub(crate) fn is_process_alive(pid: u32) -> bool {
unsafe { libc::kill(pid as libc::pid_t, 0) == 0 }
}
pub(crate) fn signal_stop(pid: u32) -> Result<()> {
let result = unsafe { libc::kill(pid as libc::pid_t, libc::SIGTERM) };
if result != 0 {
let err = std::io::Error::last_os_error();
if err.raw_os_error() == Some(libc::ESRCH) {
return Ok(());
}
return Err(RuntimeError::Daemon(format!(
"failed to send SIGTERM to pid {pid}: {err}"
)));
}
Ok(())
}
pub(crate) fn signal_reload(pid: u32) -> Result<()> {
let result = unsafe { libc::kill(pid as libc::pid_t, libc::SIGHUP) };
if result != 0 {
let err = std::io::Error::last_os_error();
if err.raw_os_error() == Some(libc::ESRCH) {
return Ok(());
}
return Err(RuntimeError::Daemon(format!(
"failed to send SIGHUP to pid {pid}: {err}"
)));
}
Ok(())
}
pub(crate) fn signal_kill(pid: u32) -> Result<()> {
let result = unsafe { libc::kill(pid as libc::pid_t, libc::SIGKILL) };
if result != 0 {
let err = std::io::Error::last_os_error();
if err.raw_os_error() == Some(libc::ESRCH) {
return Ok(());
}
return Err(RuntimeError::Daemon(format!(
"failed to send SIGKILL to pid {pid}: {err}"
)));
}
Ok(())
}