Skip to content

Commit 1bc75f0

Browse files
committed
fix: hanging reboot
Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com>
1 parent 84ea29a commit 1bc75f0

File tree

14 files changed

+169
-262
lines changed

14 files changed

+169
-262
lines changed

src/main.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ pub mod web_service;
77

88
use env_logger::{Builder, Env, Target};
99
use log::{error, info};
10-
use std::{env, io::Write, process};
10+
use std::{io::Write, process};
1111
use twin::Twin;
1212

1313
#[tokio::main]
14-
async fn main() {
14+
async fn main() -> process::ExitCode {
1515
log_panics::init();
1616

1717
let mut builder = if cfg!(debug_assertions) {
@@ -45,18 +45,10 @@ async fn main() {
4545
if let Err(e) = Twin::run().await {
4646
error!("application error: {e:#}");
4747

48-
process::exit(1);
48+
return process::ExitCode::FAILURE;
4949
}
5050

5151
info!("application shutdown");
5252

53-
// FIXME:
54-
// under some circumstances the app can hang at termination what can be
55-
// worked around by explicitly issuing exit here.
56-
// to ease further examination of that problem allow setting an
57-
// environment variable to skip the workaround.
58-
if env::var("DONT_EXPLICITLY_EXIT_ON_TERMINATION").is_err() {
59-
// ensure that we terminate here right now
60-
process::exit(0);
61-
}
53+
process::ExitCode::SUCCESS
6254
}

src/systemd/mod.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,18 @@ pub fn sd_notify_ready() {
1818
}
1919

2020
#[cfg(not(feature = "mock"))]
21-
pub async fn reboot() -> Result<()> {
21+
pub async fn reboot(reason: &str, extra_info: &str) -> Result<()> {
22+
use crate::reboot_reason;
2223
use anyhow::Context;
2324
use log::{debug, error};
2425
use std::process::Command;
2526

2627
info!("systemd::reboot");
2728

29+
reboot_reason::write_reboot_reason(reason, extra_info).context(format!(
30+
"reboot: failed to write reason '{reason}' with info '{extra_info}'"
31+
))?;
32+
2833
//journalctl seems not to have a dbus api
2934
match Command::new("sudo").args(["journalctl", "--sync"]).status() {
3035
Ok(status) if !status.success() => error!("reboot: failed to execute 'journalctl --sync'"),
@@ -44,9 +49,6 @@ pub async fn reboot() -> Result<()> {
4449
)
4550
.await
4651
.context("reboot: call_method() failed")?;
47-
48-
debug!("reboot: succeeded to call systemd reboot");
49-
5052
Ok(())
5153
}
5254

@@ -74,6 +76,6 @@ pub async fn wait_for_system_running() -> Result<()> {
7476
}
7577

7678
#[cfg(feature = "mock")]
77-
pub async fn reboot() -> Result<()> {
79+
pub async fn reboot(_reason: &str, _extra_info: &str) -> Result<()> {
7880
Ok(())
7981
}

src/twin/factory_reset.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use crate::{
22
bootloader_env,
33
common::from_json_file,
4-
reboot_reason, systemd,
4+
systemd,
55
twin::{Feature, feature::*},
66
web_service,
77
};
88
use anyhow::{Context, Result, bail};
99
use azure_iot_sdk::client::IotMessage;
10-
use log::{debug, error, info, warn};
10+
use log::{debug, info, warn};
1111
use notify_debouncer_full::{Debouncer, NoCache, notify::*};
1212
use serde::{Deserialize, Serialize};
1313
use serde_json::{from_reader, json};
@@ -263,13 +263,7 @@ impl FactoryReset {
263263
}
264264

265265
bootloader_env::set("factory-reset", &serde_json::to_string(&cmd)?)?;
266-
267-
if let Err(e) =
268-
reboot_reason::write_reboot_reason("factory-reset", "initiated by portal or API")
269-
{
270-
error!("reset_to_factory_settings: failed to write reboot reason with {e:#}");
271-
}
272-
systemd::reboot().await?;
266+
systemd::reboot("factory-reset", "initiated by portal or API").await?;
273267
Ok(None)
274268
}
275269
}

src/twin/feature/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub enum Command {
3737
ReloadNetwork,
3838
RunFirmwareUpdate(firmware_update::RunUpdateCommand),
3939
SetWaitOnlineTimeout(reboot::SetWaitOnlineTimeoutCommand),
40-
ValidateUpdateAuthenticated(bool),
40+
ValidateUpdate(bool),
4141
UserConsent(consent::UserConsentCommand),
4242
}
4343

@@ -62,7 +62,7 @@ impl Command {
6262
ReloadNetwork => TypeId::of::<network::Network>(),
6363
RunFirmwareUpdate(_) => TypeId::of::<firmware_update::FirmwareUpdate>(),
6464
SetWaitOnlineTimeout(_) => TypeId::of::<reboot::Reboot>(),
65-
ValidateUpdateAuthenticated(_) => TypeId::of::<firmware_update::FirmwareUpdate>(),
65+
ValidateUpdate(_) => TypeId::of::<firmware_update::FirmwareUpdate>(),
6666
UserConsent(_) => TypeId::of::<consent::DeviceUpdateConsent>(),
6767
}
6868
}

src/twin/firmware_update/mod.rs

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub mod update_validation;
66
use crate::{
77
bootloader_env,
88
common::{RootPartition, from_json_file, path_ends_with, to_json_file},
9-
reboot_reason, systemd,
9+
systemd,
1010
systemd::{unit::UnitAction, watchdog::WatchdogManager},
1111
twin::{
1212
Feature,
@@ -182,7 +182,7 @@ impl Feature for FirmwareUpdate {
182182
match cmd {
183183
Command::LoadFirmwareUpdate(cmd) => self.load(&cmd.update_file_path).await,
184184
Command::RunFirmwareUpdate(cmd) => self.run(cmd.validate_iothub_connection).await,
185-
Command::ValidateUpdateAuthenticated(authenticated) => {
185+
Command::ValidateUpdate(authenticated) => {
186186
self.update_validation
187187
.set_authenticated(*authenticated)
188188
.await?;
@@ -197,11 +197,11 @@ impl FirmwareUpdate {
197197
const FIRMWARE_UPDATE_VERSION: u8 = 1;
198198
const ID: &'static str = "firmware_update";
199199

200-
pub fn new(update_validation: UpdateValidation) -> Self {
201-
FirmwareUpdate {
200+
pub async fn new() -> Result<Self> {
201+
Ok(FirmwareUpdate {
202202
swu_file_path: None,
203-
update_validation,
204-
}
203+
update_validation: UpdateValidation::new().await?,
204+
})
205205
}
206206

207207
async fn load<P>(&mut self, path: P) -> CommandResult
@@ -394,11 +394,7 @@ impl FirmwareUpdate {
394394
true,
395395
)?;
396396

397-
if let Err(e) = reboot_reason::write_reboot_reason("swupdate", "local update") {
398-
error!("failed to write reboot reason: {e:#}");
399-
}
400-
401-
systemd::reboot().await?;
397+
systemd::reboot("swupdate", "local update").await?;
402398

403399
info!("update succeeded");
404400

@@ -480,8 +476,7 @@ mod tests {
480476
crate::common::set_env_var("UPDATE_FOLDER_PATH", update_folder);
481477
crate::common::set_env_var("DEVICE_UPDATE_PATH", du_config_file);
482478
crate::common::set_env_var("SW_VERSIONS_PATH", sw_versions_file);
483-
let (tx_validated, mut _rx_validated) = tokio::sync::oneshot::channel();
484-
let update_validation = UpdateValidation::new(tx_validated).await.unwrap();
479+
let update_validation = UpdateValidation::new().await.unwrap();
485480

486481
let mut firmware_update = FirmwareUpdate {
487482
swu_file_path: None,
@@ -505,8 +500,7 @@ mod tests {
505500
crate::common::set_env_var("UPDATE_FOLDER_PATH", update_folder);
506501
crate::common::set_env_var("DEVICE_UPDATE_PATH", du_config_file);
507502
crate::common::set_env_var("SW_VERSIONS_PATH", &sw_versions_file);
508-
let (tx_validated, mut _rx_validated) = tokio::sync::oneshot::channel();
509-
let update_validation = UpdateValidation::new(tx_validated).await.unwrap();
503+
let update_validation = UpdateValidation::new().await.unwrap();
510504

511505
let mut firmware_update = FirmwareUpdate {
512506
swu_file_path: None,
@@ -553,8 +547,7 @@ mod tests {
553547
crate::common::set_env_var("UPDATE_FOLDER_PATH", update_folder);
554548
crate::common::set_env_var("DEVICE_UPDATE_PATH", &du_config_file);
555549
crate::common::set_env_var("SW_VERSIONS_PATH", sw_versions_file);
556-
let (tx_validated, mut _rx_validated) = tokio::sync::oneshot::channel();
557-
let update_validation = UpdateValidation::new(tx_validated).await.unwrap();
550+
let update_validation = UpdateValidation::new().await.unwrap();
558551

559552
let mut firmware_update = FirmwareUpdate {
560553
swu_file_path: None,

0 commit comments

Comments
 (0)