286 lines
10 KiB
Diff
286 lines
10 KiB
Diff
From 5c9eb30727331780e01cd34293801efd38aa787d Mon Sep 17 00:00:00 2001
|
|
From: huyubiao <h13958451065@163.com>
|
|
Date: Fri, 16 Jun 2023 15:32:28 +0800
|
|
Subject: [PATCH] fix: init uses SIGABRT to reexec sysmaster, increase signal
|
|
permissions
|
|
|
|
---
|
|
core/bin/main.rs | 46 ++++++++++++++++----------------
|
|
core/bin/manager/mod.rs | 9 ++++++-
|
|
exts/init/Cargo.toml | 1 -
|
|
exts/init/src/runtime/mod.rs | 33 +++++++++--------------
|
|
exts/init/src/runtime/signals.rs | 19 +++++++------
|
|
libs/constants/src/lib.rs | 2 --
|
|
7 files changed, 60 insertions(+), 62 deletions(-)
|
|
|
|
diff --git a/core/bin/main.rs b/core/bin/main.rs
|
|
index 0239ce9..7f163c7 100644
|
|
--- a/core/bin/main.rs
|
|
+++ b/core/bin/main.rs
|
|
@@ -39,7 +39,7 @@ use crate::mount::setup;
|
|
use basic::logger::{self};
|
|
use basic::process_util;
|
|
use clap::Parser;
|
|
-use libc::{c_int, getppid, prctl, PR_SET_CHILD_SUBREAPER};
|
|
+use libc::{c_int, getpid, getppid, prctl, PR_SET_CHILD_SUBREAPER};
|
|
use log::{self};
|
|
use manager::signals::EVENT_SIGNALS;
|
|
use nix::sys::resource::{self, Resource};
|
|
@@ -52,7 +52,6 @@ use std::rc::Rc;
|
|
use sysmaster::error::*;
|
|
use sysmaster::rel;
|
|
|
|
-use constants::SIG_MANAGER_REEXEC_OFFSET;
|
|
use constants::SIG_SWITCH_ROOT_OFFSET;
|
|
|
|
/// parse program arguments
|
|
@@ -106,21 +105,17 @@ fn main() -> Result<()> {
|
|
setup::mount_setup()?;
|
|
|
|
rel::reli_dir_prepare()?;
|
|
- let switch = rel::reli_debug_get_switch();
|
|
- log::info!("sysmaster initialize with switch: {}.", switch);
|
|
+ let self_recovery_enable = rel::reli_debug_get_switch();
|
|
+ log::info!("sysmaster self_recovery_enable: {}.", self_recovery_enable);
|
|
|
|
- initialize_runtime(switch)?;
|
|
+ initialize_runtime(self_recovery_enable)?;
|
|
|
|
let manager = Manager::new(Mode::System, Action::Run, manager_config);
|
|
|
|
- // enable clear, mutex with install_crash_handler
|
|
- if !switch {
|
|
- if !args.deserialize {
|
|
- manager.debug_clear_restore();
|
|
- log::info!("debug: clear data restored.");
|
|
- }
|
|
- // if switch is false unregister init's reexec signal.
|
|
- register_reexec_signal(false);
|
|
+ // enable clear
|
|
+ if !self_recovery_enable && !args.deserialize {
|
|
+ manager.debug_clear_restore();
|
|
+ log::info!("debug: clear data restored.");
|
|
}
|
|
|
|
manager.setup_cgroup()?;
|
|
@@ -144,10 +139,13 @@ fn main() -> Result<()> {
|
|
Ok(())
|
|
}
|
|
|
|
-fn initialize_runtime(switch: bool) -> Result<()> {
|
|
- if switch {
|
|
+fn initialize_runtime(self_recovery_enable: bool) -> Result<()> {
|
|
+ if self_recovery_enable {
|
|
install_crash_handler();
|
|
log::info!("install crash handler.");
|
|
+ } else {
|
|
+ // if self_recovery_enable is false unregister init's reexec signal.
|
|
+ register_reexec_signal(false);
|
|
}
|
|
|
|
#[cfg(feature = "linux")]
|
|
@@ -222,7 +220,7 @@ fn install_crash_handler() {
|
|
Signal::SIGABRT,
|
|
Signal::SIGSYS,
|
|
];
|
|
- let handler = SigHandler::Handler(crash);
|
|
+ let handler = SigHandler::SigAction(crash);
|
|
let flags = SaFlags::SA_NODEFER;
|
|
let action = SigAction::new(handler, flags, SigSet::empty());
|
|
for &signal in signals.iter() {
|
|
@@ -232,11 +230,14 @@ fn install_crash_handler() {
|
|
}
|
|
}
|
|
|
|
-extern "C" fn crash(signo: c_int) {
|
|
- let _signal = Signal::try_from(signo).unwrap(); // debug
|
|
-
|
|
- let args: Vec<String> = env::args().collect();
|
|
- do_reexecute(&args, false);
|
|
+extern "C" fn crash(signo: c_int, siginfo: *mut libc::siginfo_t, _con: *mut libc::c_void) {
|
|
+ let signal = Signal::try_from(signo).unwrap(); // debug
|
|
+ if (signal == Signal::SIGABRT && unsafe { (*siginfo).si_pid() == getppid() })
|
|
+ || unsafe { (*siginfo).si_pid() == getpid() }
|
|
+ {
|
|
+ let args: Vec<String> = env::args().collect();
|
|
+ do_reexecute(&args, false);
|
|
+ }
|
|
}
|
|
|
|
fn execarg_build_default() -> (String, Vec<String>) {
|
|
@@ -265,8 +266,7 @@ extern "C" fn crash_none(_signo: c_int, _siginfo: *mut libc::siginfo_t, _con: *m
|
|
}
|
|
|
|
fn register_reexec_signal(enable: bool) {
|
|
- let manager_signal: signal::Signal =
|
|
- unsafe { std::mem::transmute(libc::SIGRTMIN() + SIG_MANAGER_REEXEC_OFFSET) };
|
|
+ let manager_signal: Signal = Signal::SIGABRT;
|
|
let handler = match enable {
|
|
true => SigHandler::SigAction(crash_reexec),
|
|
false => SigHandler::SigAction(crash_none),
|
|
diff --git a/core/bin/manager/mod.rs b/core/bin/manager/mod.rs
|
|
index e972cc7..7bd16e0 100644
|
|
--- a/core/bin/manager/mod.rs
|
|
+++ b/core/bin/manager/mod.rs
|
|
@@ -59,6 +59,12 @@ impl SignalMgr {
|
|
SignalMgr { um: Rc::clone(&um) }
|
|
}
|
|
fn reexec(&self) -> Result<i32> {
|
|
+ self.um.set_state(State::ReExecute);
|
|
+ Ok(1)
|
|
+ }
|
|
+
|
|
+ fn reload(&self) -> Result<i32> {
|
|
+ self.um.set_state(State::ReLoad);
|
|
Ok(1)
|
|
}
|
|
}
|
|
@@ -70,7 +76,8 @@ impl SignalDispatcher for SignalMgr {
|
|
return Ok(1);
|
|
}
|
|
match signal.ssi_signo as libc::c_int {
|
|
- libc::SIGHUP | libc::SIGTERM => self.reexec(),
|
|
+ libc::SIGHUP => self.reload(),
|
|
+ libc::SIGTERM => self.reexec(),
|
|
libc::SIGCHLD => Ok(self.um.child_sigchld_enable(true)),
|
|
/* Kernel will send SIGINT to PID1 when users press ctrl-alt-del,
|
|
* init should forward SIGINT to sysmaster. */
|
|
diff --git a/exts/init/Cargo.toml b/exts/init/Cargo.toml
|
|
index e3c0198..e351b61 100644
|
|
--- a/exts/init/Cargo.toml
|
|
+++ b/exts/init/Cargo.toml
|
|
@@ -9,4 +9,3 @@ edition = "2021"
|
|
constants = { version = "0.1.0", path = "../../libs/constants" }
|
|
libc = "0.2.*"
|
|
nix = "0.24"
|
|
-signal-hook-registry = "1.4.0"
|
|
diff --git a/exts/init/src/runtime/mod.rs b/exts/init/src/runtime/mod.rs
|
|
index e37ff01..d11d8f2 100644
|
|
--- a/exts/init/src/runtime/mod.rs
|
|
+++ b/exts/init/src/runtime/mod.rs
|
|
@@ -33,7 +33,6 @@ use std::rc::Rc;
|
|
|
|
use constants::SIG_SWITCH_ROOT_OFFSET;
|
|
const INVALID_PID: i32 = -1;
|
|
-const MANAGER_SIG_OFFSET: i32 = 7;
|
|
const SYSMASTER_PATH: &str = "/usr/lib/sysmaster/sysmaster";
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
|
|
@@ -152,12 +151,7 @@ impl RunTime {
|
|
|
|
self.comm.finish();
|
|
|
|
- unsafe {
|
|
- libc::kill(
|
|
- self.sysmaster_pid.into(),
|
|
- libc::SIGRTMIN() + MANAGER_SIG_OFFSET,
|
|
- )
|
|
- };
|
|
+ unsafe { libc::kill(self.sysmaster_pid.into(), libc::SIGABRT) };
|
|
}
|
|
|
|
fn reexec_comm_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> {
|
|
@@ -187,11 +181,10 @@ impl RunTime {
|
|
|
|
fn reexec_signal_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> {
|
|
if let Some(siginfo) = self.signals.read(event)? {
|
|
- let signo = siginfo.ssi_signo as i32;
|
|
- match signo {
|
|
- _x if self.signals.is_zombie(signo) => self.do_recycle(),
|
|
- _x if self.signals.is_restart(signo) => self.do_reexec(),
|
|
- _x if self.signals.is_unrecover(signo) => self.change_to_unrecover(),
|
|
+ match siginfo {
|
|
+ _x if self.signals.is_zombie(siginfo) => self.do_recycle(),
|
|
+ _x if self.signals.is_restart(siginfo) => self.do_reexec(),
|
|
+ _x if self.signals.is_unrecover(siginfo) => self.change_to_unrecover(),
|
|
_ => {}
|
|
}
|
|
}
|
|
@@ -200,11 +193,10 @@ impl RunTime {
|
|
|
|
fn run_signal_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> {
|
|
if let Some(siginfo) = self.signals.read(event)? {
|
|
- let signo = siginfo.ssi_signo as i32;
|
|
- match signo {
|
|
- _x if self.signals.is_zombie(signo) => self.do_recycle(),
|
|
- _x if self.signals.is_restart(signo) => self.do_reexec(),
|
|
- _x if self.signals.is_switch_root(signo) => self.send_switch_root_signal(),
|
|
+ match siginfo {
|
|
+ _x if self.signals.is_zombie(siginfo) => self.do_recycle(),
|
|
+ _x if self.signals.is_restart(siginfo) => self.do_reexec(),
|
|
+ _x if self.signals.is_switch_root(siginfo) => self.send_switch_root_signal(),
|
|
_ => {}
|
|
}
|
|
}
|
|
@@ -213,15 +205,14 @@ impl RunTime {
|
|
|
|
fn unrecover_signal_dispatch(&mut self, event: EpollEvent) -> Result<(), Errno> {
|
|
if let Some(siginfo) = self.signals.read(event)? {
|
|
- let signo = siginfo.ssi_signo as i32;
|
|
- match signo {
|
|
- _x if self.signals.is_zombie(signo) => {
|
|
+ match siginfo {
|
|
+ _x if self.signals.is_zombie(siginfo) => {
|
|
self.signals.recycle_zombie();
|
|
if self.is_sysmaster(siginfo.ssi_pid as i32) && self.switching {
|
|
self.reexec_self()
|
|
}
|
|
}
|
|
- _x if self.signals.is_restart(signo) => self.do_recreate(),
|
|
+ _x if self.signals.is_restart(siginfo) => self.do_recreate(),
|
|
_ => {}
|
|
}
|
|
}
|
|
diff --git a/exts/init/src/runtime/signals.rs b/exts/init/src/runtime/signals.rs
|
|
index eee088c..1c3059c 100644
|
|
--- a/exts/init/src/runtime/signals.rs
|
|
+++ b/exts/init/src/runtime/signals.rs
|
|
@@ -81,20 +81,23 @@ impl Signals {
|
|
}
|
|
}
|
|
|
|
- pub fn is_zombie(&self, signo: i32) -> bool {
|
|
- self.zombie_signal == signo
|
|
+ pub fn is_zombie(&self, siginfo: libc::signalfd_siginfo) -> bool {
|
|
+ self.zombie_signal as u32 == siginfo.ssi_signo
|
|
}
|
|
|
|
- pub fn is_restart(&self, signo: i32) -> bool {
|
|
- self.restart_signal == signo
|
|
+ pub fn is_restart(&self, siginfo: libc::signalfd_siginfo) -> bool {
|
|
+ self.restart_signal as u32 == siginfo.ssi_signo
|
|
}
|
|
|
|
- pub fn is_unrecover(&self, signo: i32) -> bool {
|
|
- self.unrecover_signal == signo
|
|
+ pub fn is_unrecover(&self, siginfo: libc::signalfd_siginfo) -> bool {
|
|
+ if 0 == siginfo.ssi_uid {
|
|
+ return self.unrecover_signal as u32 == siginfo.ssi_signo;
|
|
+ }
|
|
+ false
|
|
}
|
|
|
|
- pub fn is_switch_root(&self, signo: i32) -> bool {
|
|
- self.switch_root_signal == signo
|
|
+ pub fn is_switch_root(&self, siginfo: libc::signalfd_siginfo) -> bool {
|
|
+ self.switch_root_signal as u32 == siginfo.ssi_signo
|
|
}
|
|
|
|
pub fn create_signals_epoll(&mut self) -> Result<(), Errno> {
|
|
diff --git a/libs/constants/src/lib.rs b/libs/constants/src/lib.rs
|
|
index 7c918aa..b1db27c 100644
|
|
--- a/libs/constants/src/lib.rs
|
|
+++ b/libs/constants/src/lib.rs
|
|
@@ -12,8 +12,6 @@
|
|
|
|
//! Common used constants by init, sysmaster and other extensions.
|
|
|
|
-/// Signal used to reexecute sysmaster, SIGRTMIN+7
|
|
-pub const SIG_MANAGER_REEXEC_OFFSET: i32 = 7;
|
|
/// Signal used run unrecover, SIGRTMIN+8
|
|
pub const SIG_RUN_UNRECOVER_OFFSET: i32 = 8;
|
|
/// Signal used to restart the manager, SIGRTMIN+9
|
|
--
|
|
2.33.0
|
|
|