Skip to content

Commit

Permalink
Fix wakeup after system sleep
Browse files Browse the repository at this point in the history
References #62
  • Loading branch information
X3n0m0rph59 committed Apr 23, 2021
1 parent e16fdf0 commit 6c43a3c
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 88 deletions.
14 changes: 7 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion eruption-hotplug-helper/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "eruption-hotplug-helper"
version = "0.0.2"
version = "0.0.5"
authors = ["X3n0m0rph59 <x3n0m0rph59@gmail.com>"]
edition = "2018"
description = "A utility used to notify Eruption about device hotplug events"
Expand Down
243 changes: 166 additions & 77 deletions eruption-hotplug-helper/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use clap::Clap;
use log::*;
use std::{
env, io,
path::Path,
process::{Command, Stdio},
thread,
time::Duration,
Expand Down Expand Up @@ -115,112 +116,200 @@ pub async fn main() -> std::result::Result<(), eyre::Error> {
let opts = Options::parse();
match opts.command {
Subcommands::Hotplug => {
log::info!("A hotplug event has been triggered, notifying the Eruption daemon...");

// place a lockfile, so we don't run into loops
match lockfile::Lockfile::create("/run/lock/eruption-hotplug-helper.lock") {
Ok(lock_file) => {
log::debug!("Checking whether the system is fully booted...");
if Path::new("/run/lock/eruption-sleep.lock").exists() {
log::info!("Waking up from system sleep...");

// sleep until udev has settled
log::info!("Waiting for the devices to settle...");

// udevadm settle may/will deadlock since eruption adds (virtual) devices to udev
let status = Command::new("/usr/bin/udevadm")
.arg("settle")
.stdout(Stdio::null())
.status();

let result = Command::new("/usr/bin/systemctl")
.arg("is-system-running")
.stdout(Stdio::null())
.status();
if let Err(e) = status {
// udev-settle has failed, sleep a while and let the devices settle

match result {
Ok(status) if status.success() => {
// sleep until udev has settled
log::info!("Waiting for the devices to settle...");
log::error!("udevadm settle has failed: {}", e);

// udevadm settle may/will deadlock since eruption adds (virtual) devices to udev
let status = Command::new("/usr/bin/udevadm")
.arg("settle")
.stdout(Stdio::null())
.status();
thread::sleep(Duration::from_millis(2500));
} else {
// sleep a while just to be safe
thread::sleep(Duration::from_millis(500));

log::info!("Done, all devices have settled");
}

if let Err(e) = status {
// udev-settle has failed, sleep a while and let the devices settle
log::info!("Now starting the eruption.service...");

// TODO: Implement a D-Bus based notification interface,
// simply restart the eruption.service for now
let status = Command::new("/usr/bin/systemctl")
.arg("start")
.arg("eruption.service")
.stdout(Stdio::null())
.status()?;

if status.success() {
// wait for the eruption.service to be fully operational...
log::info!("Waiting for Eruption to be fully operational...");

let mut retry_counter = 0;

'WAIT_START_LOOP: loop {
let result = Command::new("/usr/bin/systemctl")
.arg("is-active")
.arg("eruption.service")
.stdout(Stdio::null())
.status();

match result {
Ok(status) => {
if status.success() {
log::info!(
"Eruption has been started successfully, exiting now"
);

break 'WAIT_START_LOOP;
} else {
thread::sleep(Duration::from_millis(1000));

if retry_counter >= 5 {
log::error!(
"Timeout while starting eruption.service"
);

log::error!("udevadm settle has failed: {}", e);
break 'WAIT_START_LOOP;
} else {
retry_counter += 1;
}
}
}

thread::sleep(Duration::from_millis(2500));
} else {
// sleep a while just to be safe
thread::sleep(Duration::from_millis(500));
Err(e) => {
log::error!(
"Error while waiting for Eruption to start: {}",
e
);

log::info!("Done, all devices have settled");
break 'WAIT_START_LOOP;
}
}
}
} else {
log::error!("Could not start Eruption, an error occurred");
}
} else {
log::info!(
"A hotplug event has been triggered, notifying the Eruption daemon..."
);

log::debug!("Checking whether the system is fully booted...");

let result = Command::new("/usr/bin/systemctl")
.arg("is-system-running")
.stdout(Stdio::null())
.status();

log::info!("Now restarting the eruption.service...");

// TODO: Implement a D-Bus based notification interface,
// simply restart the eruption.service for now
let status = Command::new("/usr/bin/systemctl")
.arg("restart")
.arg("eruption.service")
.stdout(Stdio::null())
.status()?;

if status.success() {
// wait for the eruption.service to be fully operational...
log::info!("Waiting for Eruption to be fully operational...");

let mut retry_counter = 0;

'WAIT_LOOP: loop {
let result = Command::new("/usr/bin/systemctl")
.arg("is-active")
.arg("eruption.service")
.stdout(Stdio::null())
.status();

match result {
Ok(status) => {
if status.success() {
log::info!(
match result {
Ok(status) if status.success() => {
// sleep until udev has settled
log::info!("Waiting for the devices to settle...");

// udevadm settle may/will deadlock since eruption adds (virtual) devices to udev
let status = Command::new("/usr/bin/udevadm")
.arg("settle")
.stdout(Stdio::null())
.status();

if let Err(e) = status {
// udev-settle has failed, sleep a while and let the devices settle

log::error!("udevadm settle has failed: {}", e);

thread::sleep(Duration::from_millis(2500));
} else {
// sleep a while just to be safe
thread::sleep(Duration::from_millis(500));

log::info!("Done, all devices have settled");
}

log::info!("Now restarting the eruption.service...");

// TODO: Implement a D-Bus based notification interface,
// simply restart the eruption.service for now
let status = Command::new("/usr/bin/systemctl")
.arg("restart")
.arg("eruption.service")
.stdout(Stdio::null())
.status()?;

if status.success() {
// wait for the eruption.service to be fully operational...
log::info!("Waiting for Eruption to be fully operational...");

let mut retry_counter = 0;

'WAIT_RESTART_LOOP: loop {
let result = Command::new("/usr/bin/systemctl")
.arg("is-active")
.arg("eruption.service")
.stdout(Stdio::null())
.status();

match result {
Ok(status) => {
if status.success() {
log::info!(
"Notification sent successfully, exiting now"
);

break 'WAIT_LOOP;
} else {
thread::sleep(Duration::from_millis(1000));
break 'WAIT_RESTART_LOOP;
} else {
thread::sleep(Duration::from_millis(1000));

if retry_counter >= 5 {
log::error!(
if retry_counter >= 5 {
log::error!(
"Timeout while restarting eruption.service"
);

break 'WAIT_LOOP;
} else {
retry_counter += 1;
break 'WAIT_RESTART_LOOP;
} else {
retry_counter += 1;
}
}
}
}

Err(e) => {
log::error!(
"Error while waiting for Eruption to start: {}",
e
);
Err(e) => {
log::error!(
"Error while waiting for Eruption to start: {}",
e
);

break 'WAIT_LOOP;
break 'WAIT_RESTART_LOOP;
}
}
}
} else {
log::error!("Could not notify Eruption, an error occurred");
}
} else {
log::error!("Could not notify Eruption, an unknown error occurred");
}
}

Err(e) => {
log::error!(
"Could not determine whether the system is still booting: {}",
e
);
}
Err(e) => {
log::error!(
"Could not determine whether the system is still booting: {}",
e
);
}

_ => {
log::info!("System is still booting, skipping restart of Eruption");
_ => {
log::info!("System is still booting, skipping restart of Eruption");
}
}
}

Expand Down
13 changes: 10 additions & 3 deletions support/systemd/eruption-suspend.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
#!/bin/sh

if [ "$1" = "pre" ] ; then
# stop eruption.service when entering suspend or hibernate
# prepare Eruption for system sleep
touch /run/lock/eruption-hotplug-helper.lock

systemctl stop eruption-hotplug-helper.service
systemctl stop eruption.service

touch /run/lock/eruption-sleep.lock
else
# start eruption.service when waking up from suspend or hibernate
systemctl start eruption.service
# wake up Eruption after system sleep
rm /run/lock/eruption-hotplug-helper.lock
systemctl start eruption-hotplug-helper.service
rm /run/lock/eruption-sleep.lock
fi

0 comments on commit 6c43a3c

Please sign in to comment.