-
Notifications
You must be signed in to change notification settings - Fork 43
Description
There appears to be a bug on linux where a process’s timeout is consistently biased: the process is terminated too early by a sub-second offset that remains constant during a single boot but changes after rebooting.
Using this example, I got rough values for the actual time till a timeout from 5 different reboots of my system:
replicate(10, {
start_time <- Sys.time()
processx::run("sleep", "10", timeout = 3, error_on_status = FALSE)
end_time <- Sys.time()
difftime(end_time, start_time, units = "secs")
})
# Boot 1: 2.672711 2.667453 2.670226 2.670044 2.670001 2.672757 2.668645 2.669582 2.669642 2.669321
# Boot 2: 3.002664 2.976912 2.980564 2.979576 2.979316 2.984085 2.977271 2.979840 2.979048 2.981039
# Boot 3: 2.609917 2.586380 2.590400 2.590042 2.590023 2.591098 2.588827 2.589941 2.589849 2.590309
# Boot 4: 2.138885 2.106352 2.108275 2.106977 2.100902 2.111049 2.109790 2.110651 2.108229 2.110446
# Boot 5: 2.629206 2.606612 2.610635 2.609579 2.610023 2.620473 2.609882 2.610334 2.609502 2.610581This is what @mb706 and I could figure out:
Internally, the timeout is determined by Sys.time() - start_time > timeout in run_manage():
Lines 410 to 414 in 6a16b63
| if ( | |
| !is.null(timeout) && | |
| is.finite(timeout) && | |
| Sys.time() - start_time > timeout | |
| ) { |
with
start_time ultimately getting defined here:Lines 183 to 196 in 6a16b63
| ct = processx__create_time_since_boot(pid); | |
| if (ct == 0) return 0.0; | |
| bt = processx__boot_time(); | |
| if (bt == 0) return 0.0; | |
| /* Query if not yet queried */ | |
| if (processx__linux_clock_period == 0) { | |
| clock = sysconf(_SC_CLK_TCK); | |
| if (clock == -1) return 0.0; | |
| processx__linux_clock_period = 1.0 / clock; | |
| } | |
| return bt + ct * processx__linux_clock_period; |
Here, ct gets read from the field starttime in /proc/<pid>/stat and bt seems to get defined through ps::ps_boot_time() in .onLoad(), which reads the btime field in /proc/stat.
However, the boot time in /proc/stat is only accurate in seconds.
If this is rounded down, that would explain why processx would think the process is older than it actually is.
This might also relate to this issue: #394
> sessioninfo::session_info()
─ Session info ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────
setting value
version R version 4.5.1 (2025-06-13)
os Linux Mint 22
system x86_64, linux-gnu
ui X11
language en_US:en
collate de_DE.UTF-8
ctype de_DE.UTF-8
tz Europe/Berlin
date 2026-02-01
pandoc 3.1.3 @ /usr/bin/pandoc
quarto 1.7.29 @ /opt/quarto/bin/quarto
─ Packages ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
package * version date (UTC) lib source
cli 3.6.5 2025-04-23 [1] CRAN (R 4.5.0)
processx 3.8.6 2025-02-21 [1] CRAN (R 4.5.0)
ps 1.9.1 2025-04-12 [1] CRAN (R 4.5.0)
R6 2.6.1 2025-02-15 [1] CRAN (R 4.5.0)
sessioninfo 1.2.3 2025-02-05 [1] CRAN (R 4.5.0)
[1] /home/keno/R/x86_64-pc-linux-gnu-library/4.5
[2] /usr/local/lib/R/site-library
[3] /usr/lib/R/site-library
[4] /usr/lib/R/library
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────