Page MenuHomePhorge

No OneTemporary

Size
13 KB
Referenced Files
None
Subscribers
None
diff --git a/src/cc/process.cc b/src/cc/process.cc
index 266f363..bd52079 100644
--- a/src/cc/process.cc
+++ b/src/cc/process.cc
@@ -1,54 +1,73 @@
#include "../include/process.h"
#include <fcntl.h>
#include <unistd.h>
+#include <sys/wait.h>
+#include <signal.h>
#include <iostream>
namespace process {
+volatile sig_atomic_t childExitStatus = 0;
+
+void sigchld_handler(int signo) {
+ (void)signo;
+ int status;
+ while (waitpid(-1, &status, WNOHANG) > 0) {
+ childExitStatus = status;
+ }
+}
+
void Runner::New(const std::string &name, const std::string &logPath) {
std::string stdoutFileName = logPath + "/" + name + "-out.log";
std::string stderrFileName = logPath + "/" + name + "-error.log";
stdout_fd = open(stdoutFileName.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0644);
stderr_fd = open(stderrFileName.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0644);
+
+ struct sigaction sa;
+ sa.sa_handler = sigchld_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
+ if (sigaction(SIGCHLD, &sa, NULL) == -1) {
+ std::cerr << "[PMC] (cc) Error setting up SIGCHLD handler\n";
+ }
}
Runner::~Runner() {
if (stdout_fd != -1) {
close(stdout_fd);
}
if (stderr_fd != -1) {
close(stderr_fd);
}
}
int64_t Runner::Run(const std::string &command) {
pid_t pid = fork();
if (pid == -1) {
std::cerr << "[PMC] (cc) Unable to fork\n";
return -1;
} else if (pid == 0) {
setsid();
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
dup2(stdout_fd, STDOUT_FILENO);
dup2(stderr_fd, STDERR_FILENO);
if (execl("/bin/bash", "bash", "-c", command.c_str(), (char *)nullptr) == -1) {
std::cerr << "[PMC] (cc) Unable to execute the command\n";
exit(EXIT_FAILURE);
}
} else {
+ close(stdout_fd);
+ close(stderr_fd);
+
return pid;
}
- close(stdout_fd);
- close(stderr_fd);
-
return -1;
-}}
-
+}}
diff --git a/src/daemon/fork.rs b/src/daemon/fork.rs
index 6b19a40..73c0504 100644
--- a/src/daemon/fork.rs
+++ b/src/daemon/fork.rs
@@ -1,46 +1,62 @@
use global_placeholders::global;
-use std::ffi::CString;
+use std::{ffi::CString, process::exit};
pub enum Fork {
Parent(libc::pid_t),
Child,
}
pub fn chdir() -> Result<libc::c_int, i32> {
let dir = CString::new(global!("pmc.base")).expect("CString::new failed");
let res = unsafe { libc::chdir(dir.as_ptr()) };
match res {
-1 => Err(-1),
res => Ok(res),
}
}
pub fn fork() -> Result<Fork, i32> {
let res = unsafe { libc::fork() };
match res {
-1 => Err(-1),
0 => Ok(Fork::Child),
res => Ok(Fork::Parent(res)),
}
}
pub fn setsid() -> Result<libc::pid_t, i32> {
let res = unsafe { libc::setsid() };
match res {
-1 => Err(-1),
res => Ok(res),
}
}
pub fn close_fd() -> Result<(), i32> {
match unsafe { libc::close(0) } {
-1 => Err(-1),
_ => match unsafe { libc::close(1) } {
-1 => Err(-1),
_ => match unsafe { libc::close(2) } {
-1 => Err(-1),
_ => Ok(()),
},
},
}
}
+
+pub fn daemon(nochdir: bool, noclose: bool) -> Result<Fork, i32> {
+ match fork() {
+ Ok(Fork::Parent(_)) => exit(0),
+ Ok(Fork::Child) => setsid().and_then(|_| {
+ if !nochdir {
+ chdir()?;
+ }
+ if !noclose {
+ close_fd()?;
+ }
+ fork()
+ }),
+ Err(n) => Err(n),
+ }
+}
diff --git a/src/daemon/mod.rs b/src/daemon/mod.rs
index 173f388..21c826c 100644
--- a/src/daemon/mod.rs
+++ b/src/daemon/mod.rs
@@ -1,79 +1,69 @@
mod fork;
mod pid;
use crate::helpers;
use crate::process::Runner;
-use fork::{chdir, close_fd, fork, setsid, Fork};
+use fork::{daemon, Fork};
use global_placeholders::global;
use macros_rs::crashln;
-use std::{fs, thread::sleep, time::Duration};
+use std::{fs, process, thread::sleep, time::Duration};
extern "C" fn handle_termination_signal(_: libc::c_int) {
pid::remove();
- unsafe {
- libc::_exit(0);
- }
+ unsafe { libc::_exit(0) }
}
-pub fn start<F: Fn(i32)>(commands: F) {
+pub fn restore() {
+ println!("{} Spawning PMC daemon with pmc_home={}", *helpers::SUCCESS, global!("pmc.base"));
if pid::exists() {
match fs::read_to_string(global!("pmc.pid")) {
Ok(pid) => {
if let Ok(pid) = pid.trim().parse::<i32>() {
- match pid::running(pid) {
- true => commands(pid),
- false => pid::remove(),
+ if !pid::running(pid) {
+ pid::remove()
+ } else {
+ crashln!("{} The daemon is already running with PID {pid}", *helpers::FAIL)
}
}
}
Err(err) => crashln!("{} Failed to read existing PID from file: {err}", *helpers::FAIL),
}
}
- println!("{} Spawning PMC daemon with pmc_home={}", *helpers::SUCCESS, global!("pmc.base"));
- match fork() {
+ println!("{} PMC Successfully daemonized", *helpers::SUCCESS);
+ match daemon(false, false) {
+ Ok(Fork::Parent(_)) => {}
Ok(Fork::Child) => {
unsafe { libc::signal(libc::SIGTERM, handle_termination_signal as usize) };
+ pid::write(process::id());
- match setsid() {
- Ok(pid) => {
- log::trace!("Child process started with PID {}", pid);
- println!("{} PMC Successfully daemonized", *helpers::SUCCESS);
- pid::write(pid);
- }
- Err(err) => crashln!("{} setsid() failed with error: {}", *helpers::FAIL, err),
- }
-
- // if let Err(err) = chdir().and_then(|_| close_fd()).and_then(|_| fork().map_err(|err| err)) {
- // crashln!("{} Daemon creation failed with error: {}", *helpers::FAIL, err);
- // }
+ loop {
+ let runner = Runner::new();
+ if !runner.list().is_empty() {
+ for (id, item) in runner.list() {
+ let mut runner = Runner::new();
+ let name = &Some(item.name.clone());
- match chdir().and_then(|_| fork().map_err(|err| err)) {
- Ok(_status) => loop {
- let runner = Runner::new();
- if !runner.list().is_empty() {
- for (id, item) in runner.list() {
- let mut runner = Runner::new();
- let name = &Some(item.name.clone());
+ println!("name: {}, pid:{}, running: {}", item.name, item.pid, item.running);
- if let Ok(id) = id.trim().parse::<usize>() {
- if item.running {
- if !pid::running(item.pid as i32) {
- println!("restarted {}", item.pid);
- runner.restart(id, name);
- }
+ if let Ok(id) = id.trim().parse::<usize>() {
+ if item.running {
+ println!("running_pid: {}, id: {id}", pid::running(item.pid as i32));
+ if !pid::running(item.pid as i32) {
+ println!("restarted {}", item.pid);
+ runner.restart(id, name);
}
}
}
}
+ }
- sleep(Duration::from_secs(5));
- },
- Err(err) => crashln!("{} Daemon creation failed with error: {}", *helpers::FAIL, err),
+ sleep(Duration::from_secs(1));
}
}
- Ok(Fork::Parent(pid)) => commands(pid),
- Err(err) => crashln!("{} Daemon creation failed with error code: {}", *helpers::FAIL, err),
+ Err(err) => {
+ crashln!("{} Daemon creation failed with code {err}", *helpers::FAIL)
+ }
}
}
diff --git a/src/daemon/pid.rs b/src/daemon/pid.rs
index 883d794..e28aa8b 100644
--- a/src/daemon/pid.rs
+++ b/src/daemon/pid.rs
@@ -1,20 +1,20 @@
use crate::helpers;
use global_placeholders::global;
use macros_rs::crashln;
use std::fs;
pub fn exists() -> bool { fs::metadata(global!("pmc.pid")).is_ok() }
pub fn running(pid: i32) -> bool { unsafe { libc::kill(pid, 0) == 0 } }
-pub fn write(pid: i32) {
+pub fn write(pid: u32) {
if let Err(err) = fs::write(global!("pmc.pid"), pid.to_string()) {
crashln!("{} Failed to write PID to file: {}", *helpers::FAIL, err);
}
}
pub fn remove() {
log::debug!("Stale PID file detected. Removing the PID file.");
if let Err(err) = fs::remove_file(global!("pmc.pid")) {
crashln!("{} Failed to remove PID file: {}", *helpers::FAIL, err);
}
}
diff --git a/src/main.rs b/src/main.rs
index f19d315..c53ec3a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,143 +1,136 @@
mod cli;
mod daemon;
mod file;
mod globals;
mod helpers;
mod process;
mod structs;
use crate::file::Exists;
use crate::structs::Args;
use clap::{Parser, Subcommand};
use clap_verbosity_flag::Verbosity;
use global_placeholders::global;
use macros_rs::{str, string};
-use std::process::exit;
fn validate_id_script(s: &str) -> Result<Args, String> {
if let Ok(id) = s.parse::<usize>() {
Ok(Args::Id(id))
} else {
Ok(Args::Script(s.to_owned()))
}
}
#[derive(Parser)]
#[command(version = str!(cli::get_version(false)))]
struct Cli {
#[command(subcommand)]
command: Commands,
#[clap(flatten)]
verbose: Verbosity,
}
#[derive(Subcommand)]
enum Daemon {
/// Start all processes
StartAll,
/// Stop all processes
StopAll,
/// Reset process index
ResetIndex,
/// Restore daemon
Restore,
/// Check daemon
Health,
}
// add pmc restore command
#[derive(Subcommand)]
enum Commands {
/// Start/Restart a process
#[command(alias = "restart")]
Start {
#[arg(long, help = "process name")]
name: Option<String>,
#[clap(value_parser = validate_id_script)]
args: Option<Args>,
},
/// Stop/Kill a process
#[command(alias = "kill")]
Stop { id: usize },
/// Stop then remove a process
#[command(alias = "rm")]
Remove { id: usize },
/// Get env of a process
#[command(alias = "cmdline")]
Env { id: usize },
/// Get information of a process
#[command(alias = "info")]
Details { id: usize },
/// List all processes
#[command(alias = "ls")]
List {
#[arg(long, default_value_t = string!(""), help = "format output")]
format: String,
},
/// Get logs from a process
Logs {
id: usize,
#[arg(long, default_value_t = 15, help = "")]
lines: usize,
},
/// Daemon management
Daemon {
#[command(subcommand)]
command: Daemon,
},
}
fn main() {
globals::init();
let cli = Cli::parse();
let mut env = env_logger::Builder::new();
env.filter_level(cli.verbose.log_level_filter()).init();
if !Exists::folder(global!("pmc.logs")).unwrap() {
std::fs::create_dir_all(global!("pmc.logs")).unwrap();
log::info!("Created PMC log directory");
}
- daemon::start(move |pid| {
- log::trace!("Parent process started with PID {pid}");
-
- match &cli.command {
- Commands::Start { name, args } => cli::start(name, args),
- Commands::Stop { id } => cli::stop(id),
- Commands::Remove { id } => cli::remove(id),
- Commands::Env { id } => cli::env(id),
- Commands::Details { id } => cli::info(id),
- Commands::List { format } => cli::list(format),
- Commands::Logs { id, lines } => cli::logs(id, lines),
- Commands::Daemon { command } => match command {
- Daemon::StartAll => {}
- Daemon::StopAll => {}
- Daemon::ResetIndex => {}
- Daemon::Restore => {}
- Daemon::Health => {}
- },
- };
-
- exit(0);
- });
+ match &cli.command {
+ Commands::Start { name, args } => cli::start(name, args),
+ Commands::Stop { id } => cli::stop(id),
+ Commands::Remove { id } => cli::remove(id),
+ Commands::Env { id } => cli::env(id),
+ Commands::Details { id } => cli::info(id),
+ Commands::List { format } => cli::list(format),
+ Commands::Logs { id, lines } => cli::logs(id, lines),
+ Commands::Daemon { command } => match command {
+ Daemon::StartAll => {}
+ Daemon::StopAll => {}
+ Daemon::ResetIndex => {}
+ Daemon::Restore => daemon::restore(),
+ Daemon::Health => {}
+ },
+ };
}
#[cxx::bridge]
pub mod service {
unsafe extern "C++" {
include!("pmc/src/include/process.h");
include!("pmc/src/include/bridge.h");
pub fn stop(pid: i64) -> i64;
pub fn run(name: &str, log_path: &str, command: &str) -> i64;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Mar 19, 10:17 AM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
506485
Default Alt Text
(13 KB)

Event Timeline