From 6407d676d62906e10ad81cfd4d301e9ba24e8f6e Mon Sep 17 00:00:00 2001 From: radeon92 Date: Tue, 2 Nov 2021 20:43:10 +0800 Subject: [PATCH] Init sends signal about exit of child to real process1 --- .gitignore | 2 +- src/init/src/main.rs | 73 ++++++++++++++++++++++++++++++-------------- src/systemd/demo.c | 24 +++++++++++++++ 3 files changed, 75 insertions(+), 24 deletions(-) create mode 100644 src/systemd/demo.c diff --git a/.gitignore b/.gitignore index 3e573d31..a36d0931 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ target .vscode -.Cargo.lock +Cargo.lock diff --git a/src/init/src/main.rs b/src/init/src/main.rs index 1d794b70..99867e08 100644 --- a/src/init/src/main.rs +++ b/src/init/src/main.rs @@ -1,13 +1,19 @@ -use std::io::Error; +use std::fs::write; +use std::io::{self, Error}; +use std::mem::MaybeUninit; use std::path::Path; -use std::process::Command; +use std::process::{Child, Command}; -use nix::unistd::Pid; +use libc::{siginfo_t, waitid}; +use nix::libc; use nix::sys::wait::waitpid; -use nix::sys::wait::WaitPidFlag; +use nix::unistd::Pid; const PROCESS1_PATH: &'static str = "/usr/lib/process1/process1"; const SYSTEMD_PATH: &'static str = "/usr/lib/systemd/systemd"; +const PIDFILE: &'static str = "/.init.pid"; +const SELF_CODE_OFFSET: i32 = 14; +const SELF_SIG_OFFSET: i32 = 7; fn main() { let cmd = match get_command() { @@ -23,8 +29,8 @@ fn main() { } fn get_command() -> Option { - if std::env::args().count() > 2 { - panic!("More than one para, panic!!!"); + if std::env::args().count() > 2 { + panic!("More than one para, panic!!!"); } std::env::args().nth(1) @@ -43,31 +49,52 @@ fn detect_init() -> String { fn execute_mode(s: &String) -> Result<(), Error> { println!("Running to execute command : {:?}", s); - let mut command = Command::new(s); - let mut child = command.spawn()?; + let mut error_count = 0; + let mut child = create_init(s)?; loop { - let result = child.try_wait(); - match result { - Ok(Some(status)) => { - if status.success() { - println!("Successfully finished"); // shutdown - break; - } else { + let mut siginfo = MaybeUninit::::zeroed(); + let pid = unsafe { + if waitid(libc::P_ALL, 0, siginfo.as_mut_ptr(), + libc::WEXITED | libc::WNOWAIT) < 0 { + continue; + }; + siginfo.assume_init().si_pid() + }; + if pid <= 0 { + continue; + } else if pid == child.id() as i32 { + if let Ok(status) = child.wait() { + if !status.success() { + error_count += 1; + if error_count >= 3 { + break; + } println!("Exited with error, Again"); - child = command.spawn()?; + child = create_init(s)?; } } - _ => {} + } else { + println!("Receiving {} exited", pid); + send_signal(child.id(), siginfo); + let _result = waitpid(Pid::from_raw(pid), None); + println!("Reaped {}", pid); } - reap_zombie() } Ok(()) } -fn reap_zombie() { - let _result = waitpid(Pid::from_raw(-1), - Some(WaitPidFlag::WNOHANG)); - send_signal() +fn create_init(s: &String) -> io::Result { + let child = Command::new(s).spawn()?; + let _ = write(String::from(PIDFILE), child.id().to_string()); + Ok(child) } -fn send_signal() {} +fn send_signal(pid: u32, mut siginfo: MaybeUninit) { + unsafe { + siginfo.assume_init_mut().si_code -= SELF_CODE_OFFSET; + if libc::syscall(libc::SYS_rt_sigqueueinfo, pid, libc::SIGRTMIN() + SELF_SIG_OFFSET, + siginfo.as_mut_ptr()) < 0 { + println!("send signal error:{}", Error::last_os_error()) + } + } +} \ No newline at end of file diff --git a/src/systemd/demo.c b/src/systemd/demo.c new file mode 100644 index 00000000..041e71b5 --- /dev/null +++ b/src/systemd/demo.c @@ -0,0 +1,24 @@ +#include +#include +#include + +void handler(int signum, siginfo_t *siginfo, void *ucontext){ + siginfo->si_code+=14; + // follow systemd function +} + +void install_handler(){ + struct sigaction act; + act.sa_sigaction = handler; + act.sa_flags = SA_SIGINFO; + sigemptyset(&act.sa_mask); + sigaction(SIGRTMIN+7, &act, NULL); +} + +int main(){ + install_handler(); + for(int i=0;i<10;i++){ + sleep(100); + } +} + -- Gitee