switch-to-configuration-ng: fix systemd reexec/reload (#476759)
This commit is contained in:
@@ -87,6 +87,12 @@ const DRY_RELOAD_BY_ACTIVATION_LIST_FILE: &str = "/run/nixos/dry-activation-relo
|
||||
// Reuse the same default timeout that systemd uses. See https://github.com/systemd/systemd/blob/8b4278d12ec55cc3f96764bc8197e1055fbb6d3f/src/libsystemd/sd-bus/bus-internal.h#L312
|
||||
const BUS_TIMEOUT: Duration = Duration::from_secs(25);
|
||||
|
||||
// Reuse the same daemon reload/reexecute timeout that systemd uses. See https://github.com/systemd/systemd/blob/5366dbdbd44ba4dc0c914dd4daa1a5297e0b2bde/src/basic/constants.h#L18
|
||||
const DAEMON_RELOAD_TIMEOUT: Duration = Duration::from_secs(180);
|
||||
|
||||
// Used during times of waiting for D-Bus to process messages.
|
||||
const DBUS_PROCESS_TIME: Duration = Duration::from_millis(500);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
enum Action {
|
||||
Switch,
|
||||
@@ -932,7 +938,7 @@ fn block_on_jobs(
|
||||
"waiting for submitted jobs to finish, still have {} job(s)",
|
||||
submitted_jobs.borrow().len()
|
||||
);
|
||||
_ = conn.process(Duration::from_millis(500));
|
||||
_ = conn.process(DBUS_PROCESS_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -987,7 +993,7 @@ fn do_user_switch(parent_exe: String) -> anyhow::Result<()> {
|
||||
log::debug!("waiting for nixos activation to finish");
|
||||
while !*nixos_activation_done.borrow() {
|
||||
_ = dbus_conn
|
||||
.process(Duration::from_secs(500))
|
||||
.process(DBUS_PROCESS_TIME)
|
||||
.context("Failed to process dbus messages")?;
|
||||
}
|
||||
|
||||
@@ -1158,19 +1164,19 @@ won't take effect until you reboot the system.
|
||||
let submitted_jobs = Rc::new(RefCell::new(HashMap::new()));
|
||||
let finished_jobs = Rc::new(RefCell::new(HashMap::new()));
|
||||
|
||||
let systemd_reload_status = Rc::new(RefCell::new(false));
|
||||
let systemd_is_reloading = Rc::new(RefCell::new(false));
|
||||
|
||||
systemd
|
||||
.subscribe()
|
||||
.context("Failed to subscribe to systemd dbus messages")?;
|
||||
|
||||
let _systemd_reload_status = systemd_reload_status.clone();
|
||||
let _systemd_is_reloading = systemd_is_reloading.clone();
|
||||
let reloading_token = systemd
|
||||
.match_signal(
|
||||
move |signal: OrgFreedesktopSystemd1ManagerReloading,
|
||||
_: &LocalConnection,
|
||||
_msg: &Message| {
|
||||
*_systemd_reload_status.borrow_mut() = signal.active;
|
||||
*_systemd_is_reloading.borrow_mut() = signal.active;
|
||||
|
||||
true
|
||||
},
|
||||
@@ -1690,13 +1696,23 @@ won't take effect until you reboot the system.
|
||||
// just in case the new one has trouble communicating with the running pid 1.
|
||||
if restart_systemd {
|
||||
eprintln!("restarting systemd...");
|
||||
*systemd_is_reloading.borrow_mut() = true;
|
||||
_ = systemd.reexecute(); // we don't get a dbus reply here
|
||||
|
||||
log::debug!("waiting for systemd restart to finish");
|
||||
while !*systemd_reload_status.borrow() {
|
||||
|
||||
let mut reexec_time_waited = Duration::from_secs(0);
|
||||
while *systemd_is_reloading.borrow() {
|
||||
_ = dbus_conn
|
||||
.process(Duration::from_millis(500))
|
||||
.process(DBUS_PROCESS_TIME)
|
||||
.context("Failed to process dbus messages")?;
|
||||
reexec_time_waited += DBUS_PROCESS_TIME;
|
||||
if reexec_time_waited >= DAEMON_RELOAD_TIMEOUT {
|
||||
anyhow::bail!(
|
||||
"systemd daemon reexecute failed, timeout after {:?}",
|
||||
DAEMON_RELOAD_TIMEOUT
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1706,12 +1722,22 @@ won't take effect until you reboot the system.
|
||||
.context("Failed to reset failed units")?;
|
||||
|
||||
// Make systemd reload its units.
|
||||
*systemd_is_reloading.borrow_mut() = true;
|
||||
_ = systemd.reload(); // we don't get a dbus reply here
|
||||
log::debug!("waiting for systemd reload to finish");
|
||||
while !*systemd_reload_status.borrow() {
|
||||
|
||||
let mut reload_time_waited = Duration::from_secs(0);
|
||||
while *systemd_is_reloading.borrow() {
|
||||
_ = dbus_conn
|
||||
.process(Duration::from_millis(500))
|
||||
.process(DBUS_PROCESS_TIME)
|
||||
.context("Failed to process dbus messages")?;
|
||||
reload_time_waited += DBUS_PROCESS_TIME;
|
||||
if reload_time_waited >= DAEMON_RELOAD_TIMEOUT {
|
||||
anyhow::bail!(
|
||||
"systemd daemon reload failed, timeout after {:?}",
|
||||
DAEMON_RELOAD_TIMEOUT
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
dbus_conn
|
||||
|
||||
Reference in New Issue
Block a user