Refine Linux and Windows sleep inhibitor robustness

This commit is contained in:
Yaroslav Volovich
2026-02-13 21:26:03 +00:00
parent 52db1ffcb3
commit c136143be9
4 changed files with 83 additions and 24 deletions

2
codex-rs/Cargo.lock generated
View File

@@ -2505,7 +2505,7 @@ dependencies = [
"core-foundation 0.9.4",
"libc",
"tracing",
"windows-sys 0.60.2",
"windows-sys 0.52.0",
]
[[package]]

View File

@@ -17,7 +17,7 @@ tracing = { workspace = true }
[target.'cfg(target_os = "windows")'.dependencies]
tracing = { workspace = true }
windows-sys = { version = "0.60.2", features = [
windows-sys = { version = "0.52", features = [
"Win32_Foundation",
"Win32_System_Power",
"Win32_System_SystemServices",

View File

@@ -5,11 +5,15 @@ use tracing::warn;
const ASSERTION_REASON: &str = "Codex is running an active turn";
const APP_ID: &str = "codex";
// Keep the blocker process alive "long enough" without needing restarts.
// This is `i32::MAX` seconds, which is accepted by common `sleep` implementations.
const BLOCKER_SLEEP_SECONDS: &str = "2147483647";
#[derive(Debug, Default)]
pub(crate) struct LinuxSleepInhibitor {
state: InhibitState,
preferred_backend: Option<LinuxBackend>,
missing_backend_logged: bool,
}
#[derive(Debug, Default)]
@@ -36,34 +40,87 @@ impl LinuxSleepInhibitor {
impl PlatformSleepInhibitor for LinuxSleepInhibitor {
fn acquire(&mut self) {
if let InhibitState::Active { child, .. } = &mut self.state
&& child.try_wait().ok().flatten().is_none()
{
return;
}
self.state = InhibitState::Inactive;
for backend in [
LinuxBackend::SystemdInhibit,
LinuxBackend::GnomeSessionInhibit,
] {
match spawn_backend(backend) {
Ok(child) => {
self.state = InhibitState::Active { backend, child };
return;
if let InhibitState::Active { backend, child } = &mut self.state {
match child.try_wait() {
Ok(None) => return,
Ok(Some(status)) => {
warn!(
?backend,
?status,
"Linux sleep inhibitor backend exited unexpectedly; attempting fallback"
);
}
Err(error) => {
warn!(
?backend,
reason = %error,
"Failed to start Linux sleep inhibitor backend"
"Failed to query Linux sleep inhibitor backend status"
);
}
}
}
warn!("No Linux sleep inhibitor backend is available");
self.state = InhibitState::Inactive;
let should_log_backend_failures = !self.missing_backend_logged;
let backends = match self.preferred_backend {
Some(LinuxBackend::SystemdInhibit) => [
LinuxBackend::SystemdInhibit,
LinuxBackend::GnomeSessionInhibit,
],
Some(LinuxBackend::GnomeSessionInhibit) => [
LinuxBackend::GnomeSessionInhibit,
LinuxBackend::SystemdInhibit,
],
None => [
LinuxBackend::SystemdInhibit,
LinuxBackend::GnomeSessionInhibit,
],
};
for backend in backends {
match spawn_backend(backend) {
Ok(mut child) => match child.try_wait() {
Ok(None) => {
self.state = InhibitState::Active { backend, child };
self.preferred_backend = Some(backend);
self.missing_backend_logged = false;
return;
}
Ok(Some(status)) => {
if should_log_backend_failures {
warn!(
?backend,
?status,
"Linux sleep inhibitor backend exited immediately"
);
}
}
Err(error) => {
if should_log_backend_failures {
warn!(
?backend,
reason = %error,
"Failed to query Linux sleep inhibitor backend status after spawn"
);
}
}
},
Err(error) => {
if should_log_backend_failures && error.kind() != std::io::ErrorKind::NotFound {
warn!(
?backend,
reason = %error,
"Failed to start Linux sleep inhibitor backend"
);
}
}
}
}
if should_log_backend_failures {
warn!("No Linux sleep inhibitor backend is available");
self.missing_backend_logged = true;
}
}
fn release(&mut self) {

View File

@@ -39,7 +39,7 @@ impl PlatformSleepInhibitor for WindowsSleepInhibitor {
}
Err(error) => {
warn!(
reason = error,
reason = %error,
"Failed to acquire Windows sleep-prevention request"
);
}
@@ -58,7 +58,7 @@ struct PowerRequest {
}
impl PowerRequest {
fn new_execution_required(reason: &str) -> Result<Self, &'static str> {
fn new_execution_required(reason: &str) -> Result<Self, String> {
let mut wide_reason: Vec<u16> = OsStr::new(reason).encode_wide().chain(once(0)).collect();
let context = REASON_CONTEXT {
Version: POWER_REQUEST_CONTEXT_VERSION,
@@ -69,13 +69,15 @@ impl PowerRequest {
};
let handle = unsafe { PowerCreateRequest(&context) };
if handle.is_null() {
return Err("PowerCreateRequest failed");
let error = std::io::Error::last_os_error();
return Err(format!("PowerCreateRequest failed: {error}"));
}
let request_type = PowerRequestExecutionRequired;
if unsafe { PowerSetRequest(handle, request_type) } == 0 {
let error = std::io::Error::last_os_error();
let _ = unsafe { CloseHandle(handle) };
return Err("PowerSetRequest failed");
return Err(format!("PowerSetRequest failed: {error}"));
}
Ok(Self {