Files
codex/codex-rs/utils/sleep-inhibitor/src/lib.rs
T
Yaroslav VolovichandGitHub 5b71246001 fix: simplify macOS sleep inhibitor FFI (#12340)
Summary
- simplify the macOS sleep inhibitor FFI by replacing `dlopen` / `dlsym`
/ `transmute` with normal IOKit extern calls and `SAFETY` comments
- switch to cfg-selected platform implementations
(`imp::SleepInhibitor`) instead of `Box<dyn ...>`
- check in minimal IOKit bindings generated with `bindgen` and include
them from the macOS backend
- enable direct IOKit linkage in Bazel macOS builds by registering
`IOKit` in the Bazel `osx.framework(...)` toolchain extension list
- update `Cargo.lock` and `MODULE.bazel.lock` after removing the
build-time `bindgen` dependency path

Testing
- `just fmt`
- `cargo clippy -p codex-utils-sleep-inhibitor --all-targets -- -D
warnings`
- `cargo test -p codex-utils-sleep-inhibitor`
- `bazel test //codex-rs/utils/sleep-inhibitor:all --test_output=errors`
- `just bazel-lock-update`
- `just bazel-lock-check`

Context
- follow-up to #11711 addressing Ryan's review comments
- `bindgen` is used to generate the checked-in bindings file, but not at
build time
2026-02-20 09:52:21 -08:00

90 lines
2.3 KiB
Rust

//! Cross-platform helper for preventing idle sleep while a turn is running.
//!
//! On macOS this uses native IOKit power assertions instead of spawning
//! `caffeinate`, so assertion lifecycle is tied directly to Rust object lifetime.
#[cfg(not(target_os = "macos"))]
mod dummy;
#[cfg(target_os = "macos")]
mod macos;
#[cfg(not(target_os = "macos"))]
use dummy as imp;
#[cfg(target_os = "macos")]
use macos as imp;
/// Keeps the machine awake while a turn is in progress when enabled.
#[derive(Debug)]
pub struct SleepInhibitor {
enabled: bool,
platform: imp::SleepInhibitor,
}
impl SleepInhibitor {
pub fn new(enabled: bool) -> Self {
Self {
enabled,
platform: imp::SleepInhibitor::new(),
}
}
/// Update the active turn state; turns sleep prevention on/off as needed.
pub fn set_turn_running(&mut self, turn_running: bool) {
if !self.enabled {
self.release();
return;
}
if turn_running {
self.acquire();
} else {
self.release();
}
}
fn acquire(&mut self) {
self.platform.acquire();
}
fn release(&mut self) {
self.platform.release();
}
}
#[cfg(test)]
mod tests {
use super::SleepInhibitor;
#[test]
fn sleep_inhibitor_toggles_without_panicking() {
let mut inhibitor = SleepInhibitor::new(true);
inhibitor.set_turn_running(true);
inhibitor.set_turn_running(false);
}
#[test]
fn sleep_inhibitor_disabled_does_not_panic() {
let mut inhibitor = SleepInhibitor::new(false);
inhibitor.set_turn_running(true);
inhibitor.set_turn_running(false);
}
#[test]
fn sleep_inhibitor_multiple_true_calls_are_idempotent() {
let mut inhibitor = SleepInhibitor::new(true);
inhibitor.set_turn_running(true);
inhibitor.set_turn_running(true);
inhibitor.set_turn_running(true);
inhibitor.set_turn_running(false);
}
#[test]
fn sleep_inhibitor_can_toggle_multiple_times() {
let mut inhibitor = SleepInhibitor::new(true);
inhibitor.set_turn_running(true);
inhibitor.set_turn_running(false);
inhibitor.set_turn_running(true);
inhibitor.set_turn_running(false);
}
}