Fix screensaver idle timeout overflow by using 1s poll intervals with deadline tracking instead of direct millisecond conversion
This commit is contained in:
17
src/main.rs
17
src/main.rs
@@ -23,6 +23,7 @@ pub mod testutil;
|
||||
use std::os::fd::BorrowedFd;
|
||||
use std::process::ExitCode;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::time::Duration;
|
||||
|
||||
use nix::errno::Errno;
|
||||
use nix::poll::{PollFd, PollFlags, PollTimeout, poll};
|
||||
@@ -255,6 +256,8 @@ fn shed_interactive(args: ShedArgs) -> ShResult<()> {
|
||||
|
||||
readline.writer.flush_write("\x1b[?2004h")?; // enable bracketed paste mode
|
||||
|
||||
let mut screensaver_deadline: Option<Instant> = None;
|
||||
|
||||
// Main poll loop
|
||||
loop {
|
||||
write_meta(|m| {
|
||||
@@ -317,8 +320,15 @@ fn shed_interactive(args: ShedArgs) -> ShResult<()> {
|
||||
let screensaver_idle_time = read_shopts(|o| o.prompt.screensaver_idle_time);
|
||||
if screensaver_idle_time > 0 && !screensaver_cmd.is_empty() {
|
||||
exec_if_timeout = Some(screensaver_cmd);
|
||||
PollTimeout::from((screensaver_idle_time * 1000) as u16)
|
||||
if screensaver_deadline.is_none() {
|
||||
screensaver_deadline = Some(Instant::now() + Duration::from_secs(screensaver_idle_time as u64));
|
||||
}
|
||||
// We unfortunately cant just set the PollTimeout to use 'idle_time * 1000' as the timeout
|
||||
// because u16 overflows after 65 seconds (65535 ms).
|
||||
// So we set a one second timeout and check against the Instant in 'screensaver_deadline'
|
||||
PollTimeout::from(1000u16)
|
||||
} else {
|
||||
screensaver_deadline = None;
|
||||
PollTimeout::MAX
|
||||
}
|
||||
} else {
|
||||
@@ -328,7 +338,9 @@ fn shed_interactive(args: ShedArgs) -> ShResult<()> {
|
||||
match poll(&mut fds, timeout) {
|
||||
Ok(0) => {
|
||||
// We timed out.
|
||||
if let Some(cmd) = exec_if_timeout {
|
||||
if let Some(cmd) = exec_if_timeout
|
||||
&& screensaver_deadline.is_some_and(|d| Instant::now() >= d) {
|
||||
screensaver_deadline = None;
|
||||
let prepared = ReadlineEvent::Line(cmd.clone());
|
||||
let saved_hist_opt = read_shopts(|o| o.core.auto_hist);
|
||||
let _guard = scopeguard::guard(saved_hist_opt, |opt| {
|
||||
@@ -420,6 +432,7 @@ fn shed_interactive(args: ShedArgs) -> ShResult<()> {
|
||||
}
|
||||
Ok(n) => {
|
||||
readline.feed_bytes(&buffer[..n]);
|
||||
screensaver_deadline = None;
|
||||
}
|
||||
Err(Errno::EINTR) => {
|
||||
// Interrupted, continue to handle signals
|
||||
|
||||
Reference in New Issue
Block a user