fix(sre): implement PRR-01 stale mount self-healing and PRR-02 win32 console close handler
This commit is contained in:
+117
@@ -419,6 +419,114 @@ pub fn start_session_lock_monitor(
|
||||
Ok(SessionLockGuard)
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
// Console Close Event Monitor (CTRL_CLOSE_EVENT / CTRL_SHUTDOWN_EVENT)
|
||||
// ─────────────────────────────────────────────────────────────
|
||||
|
||||
#[cfg(windows)]
|
||||
static CONSOLE_CTRL_TX: std::sync::Mutex<Option<tokio::sync::mpsc::Sender<()>>> = std::sync::Mutex::new(None);
|
||||
#[cfg(windows)]
|
||||
static CONSOLE_CTRL_DRIVE: std::sync::Mutex<Option<char>> = std::sync::Mutex::new(None);
|
||||
|
||||
#[cfg(windows)]
|
||||
unsafe extern "system" fn console_ctrl_routine(ctrl_type: u32) -> i32 {
|
||||
const CTRL_C_EVENT: u32 = 0;
|
||||
const CTRL_BREAK_EVENT: u32 = 1;
|
||||
const CTRL_CLOSE_EVENT: u32 = 2;
|
||||
const CTRL_LOGOFF_EVENT: u32 = 5;
|
||||
const CTRL_SHUTDOWN_EVENT: u32 = 6;
|
||||
|
||||
match ctrl_type {
|
||||
CTRL_CLOSE_EVENT | CTRL_LOGOFF_EVENT | CTRL_SHUTDOWN_EVENT => {
|
||||
// 1. Sofortiges Notfall-Unmount direkt aus dem Win32-Callback ausführen
|
||||
if let Ok(guard) = CONSOLE_CTRL_DRIVE.lock() {
|
||||
if let Some(dl) = *guard {
|
||||
let drive_str = format!("{}:", dl.to_ascii_uppercase());
|
||||
let _ = std::process::Command::new("net")
|
||||
.args(["use", &drive_str, "/delete", "/y"])
|
||||
.output();
|
||||
}
|
||||
}
|
||||
// 2. Asynchronen Shutdown-Kanal benachrichtigen (für SQLite WAL Checkpoint)
|
||||
if let Ok(guard) = CONSOLE_CTRL_TX.lock() {
|
||||
if let Some(ref tx) = *guard {
|
||||
let _ = tx.blocking_send(());
|
||||
}
|
||||
}
|
||||
1 // TRUE: Event abgearbeitet
|
||||
}
|
||||
CTRL_C_EVENT | CTRL_BREAK_EVENT => {
|
||||
// Ctrl+C wird primär von tokio::signal::ctrl_c() behandelt
|
||||
0
|
||||
}
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// RAII Guard zur sauberen Deregistrierung des Win32 Console-Control-Handlers.
|
||||
pub struct ConsoleCtrlGuard;
|
||||
|
||||
impl Drop for ConsoleCtrlGuard {
|
||||
fn drop(&mut self) {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
extern "system" {
|
||||
fn SetConsoleCtrlHandler(
|
||||
handler: Option<unsafe extern "system" fn(u32) -> i32>,
|
||||
add: i32,
|
||||
) -> i32;
|
||||
}
|
||||
unsafe {
|
||||
SetConsoleCtrlHandler(Some(console_ctrl_routine), 0);
|
||||
}
|
||||
if let Ok(mut guard) = CONSOLE_CTRL_TX.lock() {
|
||||
*guard = None;
|
||||
}
|
||||
if let Ok(mut guard) = CONSOLE_CTRL_DRIVE.lock() {
|
||||
*guard = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Registriert einen Win32 Console Control Handler für CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT
|
||||
/// und CTRL_SHUTDOWN_EVENT, um verwaiste Netzlaufwerke beim Schließen des Konsolenfensters zu verhindern.
|
||||
pub fn start_console_ctrl_monitor(
|
||||
shutdown_tx: tokio::sync::mpsc::Sender<()>,
|
||||
drive_letter: char,
|
||||
) -> Result<ConsoleCtrlGuard> {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
extern "system" {
|
||||
fn SetConsoleCtrlHandler(
|
||||
handler: Option<unsafe extern "system" fn(u32) -> i32>,
|
||||
add: i32,
|
||||
) -> i32;
|
||||
}
|
||||
|
||||
if let Ok(mut guard) = CONSOLE_CTRL_TX.lock() {
|
||||
*guard = Some(shutdown_tx);
|
||||
}
|
||||
if let Ok(mut guard) = CONSOLE_CTRL_DRIVE.lock() {
|
||||
*guard = Some(drive_letter);
|
||||
}
|
||||
|
||||
let res = unsafe { SetConsoleCtrlHandler(Some(console_ctrl_routine), 1) };
|
||||
if res == 0 {
|
||||
bail!("Konnte Win32 SetConsoleCtrlHandler nicht registrieren");
|
||||
}
|
||||
|
||||
Ok(ConsoleCtrlGuard)
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
let _ = shutdown_tx;
|
||||
let _ = drive_letter;
|
||||
Ok(ConsoleCtrlGuard)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -438,4 +546,13 @@ mod tests {
|
||||
// Dropping monitor closes message loop and joins thread cleanly
|
||||
drop(monitor);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_console_ctrl_monitor_lifecycle() {
|
||||
let (tx, _rx) = tokio::sync::mpsc::channel(1);
|
||||
let monitor = start_console_ctrl_monitor(tx, 'Z');
|
||||
assert!(monitor.is_ok());
|
||||
drop(monitor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user