diff --git a/Cargo.lock b/Cargo.lock index 31b7cb79..e0326426 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2298,7 +2298,7 @@ dependencies = [ [[package]] name = "omnect-device-service" -version = "0.41.12" +version = "0.41.13" dependencies = [ "actix-server", "actix-web", diff --git a/Cargo.toml b/Cargo.toml index 9a2ffd80..fb494706 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" name = "omnect-device-service" readme = "README.md" repository = "https://github.com/omnect/omnect-device-service.git" -version = "0.41.12" +version = "0.41.13" [dependencies] actix-server = { version = "2.6", default-features = false } diff --git a/README.md b/README.md index 3f438f88..c1d93796 100644 --- a/README.md +++ b/README.md @@ -485,6 +485,12 @@ The availability of the feature might be suppressed by creating the following en SUPPRESS_REBOOT=true ``` +The reboot is executed with a configurable delay to allow the service to respond to the caller before the system shuts down. The delay can be configured via the `REBOOT_DELAY_MS` environment variable (default: 100ms). + +```bash +REBOOT_DELAY_MS=1000 +``` + #### Trigger reboot Direct Method Name: `reboot` diff --git a/src/systemd/mod.rs b/src/systemd/mod.rs index 9389436e..01e9e2a9 100644 --- a/src/systemd/mod.rs +++ b/src/systemd/mod.rs @@ -37,22 +37,28 @@ pub async fn reboot(reason: &str, extra_info: &str) -> Result<()> { _ => debug!("reboot: succeeded to execute 'journalctl --sync'"), } - // Trigger reboot via reboot.target using unit_action - // The job may not complete as the system shuts down, so we use a timeout - let reboot_timeout = std::time::Duration::from_secs(1); - match tokio::time::timeout( - reboot_timeout, - unit::unit_action("reboot.target", unit::UnitAction::Start, unit::Mode::Replace), - ) - .await - { - Ok(result) => result.context("reboot: failed to start reboot.target"), - Err(_) => { - // Timeout is expected as system is shutting down - debug!("reboot: timed out waiting for reboot.target (system likely shutting down)"); - Ok(()) + // Spawn reboot in background with a small delay to allow this function to return + // and the service to respond to the caller before the system shuts down + let delay_ms = std::env::var("REBOOT_DELAY_MS") + .unwrap_or("100".to_string()) + .parse::() + .unwrap_or(100); + + tokio::spawn(async move { + tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await; + debug!("triggering reboot.target"); + if let Err(e) = unit::unit_action( + "reboot.target", + unit::UnitAction::Start, + unit::Mode::Replace, + ) + .await + { + error!("failed to start reboot.target: {e:#}"); } - } + }); + + Ok(()) } pub async fn wait_for_system_running() -> Result<()> {