Skip to content

Resume interrupted futex waits, polls, and selects like Linux - #1761

Merged
Weiteng Chen (CvvT) merged 6 commits into
uliteboxfrom
weiteng/ulitebox-restart-poll-futex
Oct 30, 2026
Merged

Weiteng Chen (CvvT) merged 6 commits into
uliteboxfrom
weiteng/ulitebox-restart-poll-futex

Conversation

@CvvT

Copy link
Copy Markdown
Contributor

Follow-up to #1746, which did this for nanosleep. Blocking waits no longer fail with EINTR when interrupted by a signal that runs no handler, such as an ignored SIGCHLD queued while the sender had every signal blocked. Like Linux, they now resume or are reissued transparently.

Weiteng Chen (CvvT) and others added 6 commits October 29, 2026 23:23
Like Linux, a signal that runs no handler no longer makes blocking waits fail
with EINTR:

- A futex wait with a timeout and poll resume through restart_syscall
  (ERESTART_RESTARTBLOCK) until their original deadline, the futex wait
  checking its word again and poll reading its fds again.
- ppoll, select, and pselect6 write back the time left on every return,
  including argument errors, and are reissued (ERESTARTNOHAND). An
  interrupted call that cannot write the time back fails with EINTR.
- ppoll, pselect6, and epoll_pwait keep their temporary signal mask until the
  signals that interrupt them are delivered (saved_sigmask, like Linux's
  TIF_RESTORE_SIGMASK), so a signal the mask unblocks reaches its handler,
  whose frame saves the caller's mask. ppoll and epoll_pwait now honor their
  mask, and a NULL mask is ignored whatever its size, which glibc's
  pselect(..., NULL) relies on.

FutexManager::wait no longer loses a wake that takes the waiter as its wait
times out or is interrupted: like Linux, the waiter then reports the wake.

Instant gains a required saturating_add, so deadlines are always
representable, and absolute deadlines are capped at KTIME_MAX since boot like
relative ones. The Linux-userland broker's Instant now reads CLOCK_MONOTONIC
as a Duration.

The new wait_restart.c runner test, validated natively, checks these
behaviors deterministically.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Drop unit tests that the wait_restart.c runner test already covers
deterministically, keeping only those that check what it cannot: the
lost-wake race, futex resumption, pselect restoring its mask on bad
arguments, delivery under the restored mask, and the absolute deadline cap.
Restore the shared racing-futex test to its original form, and fold
overlapping C test cases together.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Windows recovers faulting user-memory accesses only on threads with LiteBox TLS installed, so tests that intentionally fault must run under run_test_thread. This fixes the Windows CI crash in test_pselect_with_bad_arguments_restores_its_mask and re-enables inaccessible_memory_faults and test_fallible_read on Windows.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
On macOS, run_test_thread installs per-thread TLS using the key created by
MacosUserland::new(). Calling init_platform() inside the closure meant the
key did not exist yet in a fresh nextest process, aborting with "macOS TLS
is not initialized". Initialize the platform first, as other tests do.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

🤖 SemverChecks 🤖 ⚠️ Potential breaking API changes detected ⚠️

Click for details
--- failure copy_impl_added: type now implements Copy ---

Description:
A public type now implements Copy, causing non-move closures to capture it by reference instead of moving it.
        ref: https://github.com/rust-lang/rust/issues/100905
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.51.0/src/lints/copy_impl_added.ron

Failed in:
  litebox_common_linux::FutexFlags in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:2342

--- failure enum_no_repr_variant_discriminant_changed: enum variant had its discriminant change value ---

Description:
The enum's variant had its discriminant value change. This breaks downstream code that used its value via a numeric cast like `as isize`.
        ref: https://doc.rust-lang.org/reference/items/enumerations.html#assigning-discriminant-values
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.51.0/src/lints/enum_no_repr_variant_discriminant_changed.ron

Failed in:
  variant SyscallRequest::Ppoll 66 -> 67 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:2987
  variant SyscallRequest::Pselect 67 -> 68 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:2994
  variant SyscallRequest::ArchPrctl 68 -> 69 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3002
  variant SyscallRequest::Readlink 69 -> 70 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3005
  variant SyscallRequest::Readlinkat 70 -> 71 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3010
  variant SyscallRequest::Openat 71 -> 72 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3016
  variant SyscallRequest::Ftruncate 72 -> 73 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3022
  variant SyscallRequest::Mknodat 73 -> 74 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3026
  variant SyscallRequest::Unlinkat 74 -> 75 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3032
  variant SyscallRequest::Renameat2 75 -> 76 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3037
  variant SyscallRequest::Newfstatat 76 -> 77 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3044
  variant SyscallRequest::Eventfd2 77 -> 78 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3050
  variant SyscallRequest::Pipe2 78 -> 79 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3054
  variant SyscallRequest::Clone 79 -> 80 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3058
  variant SyscallRequest::Clone3 80 -> 81 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3061
  variant SyscallRequest::SetThreadArea 81 -> 82 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3066
  variant SyscallRequest::ClockGettime 82 -> 83 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3069
  variant SyscallRequest::ClockGetres 83 -> 84 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3073
  variant SyscallRequest::ClockNanosleep 84 -> 85 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3077
  variant SyscallRequest::Gettimeofday 85 -> 86 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3083
  variant SyscallRequest::Time 86 -> 87 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3087
  variant SyscallRequest::Getrlimit 87 -> 88 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3090
  variant SyscallRequest::Setrlimit 88 -> 89 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3094
  variant SyscallRequest::Prlimit 89 -> 90 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3098
  variant SyscallRequest::SetTidAddress 90 -> 91 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3109
  variant SyscallRequest::Gettid 91 -> 92 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3112
  variant SyscallRequest::SetRobustList 92 -> 93 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3113
  variant SyscallRequest::GetRobustList 93 -> 94 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3116
  variant SyscallRequest::GetRandom 94 -> 95 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3121
  variant SyscallRequest::Getpid 95 -> 96 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3126
  variant SyscallRequest::Getppid 96 -> 97 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3127
  variant SyscallRequest::Setpgid 97 -> 98 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3128
  variant SyscallRequest::Getpgid 98 -> 99 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3132
  variant SyscallRequest::Getpgrp 99 -> 100 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3135
  variant SyscallRequest::Setsid 100 -> 101 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3136
  variant SyscallRequest::Getsid 101 -> 102 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3137
  variant SyscallRequest::Getuid 102 -> 103 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3140
  variant SyscallRequest::Geteuid 103 -> 104 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3141
  variant SyscallRequest::Getgid 104 -> 105 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3142
  variant SyscallRequest::Getegid 105 -> 106 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3143
  variant SyscallRequest::Sysinfo 106 -> 107 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3144
  variant SyscallRequest::CapGet 107 -> 108 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3147
  variant SyscallRequest::GetDirent64 108 -> 109 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3151
  variant SyscallRequest::SchedGetAffinity 109 -> 110 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3156
  variant SyscallRequest::SchedGetParam 110 -> 111 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3161
  variant SyscallRequest::SchedGetScheduler 111 -> 112 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3165
  variant SyscallRequest::SchedYield 112 -> 113 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3168
  variant SyscallRequest::Futex 113 -> 114 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3169
  variant SyscallRequest::Execve 114 -> 115 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3172
  variant SyscallRequest::Umask 115 -> 116 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3177
  variant SyscallRequest::Prctl 116 -> 117 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3180
  variant SyscallRequest::Alarm 117 -> 118 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3183
  variant SyscallRequest::Pause 118 -> 119 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3186
  variant SyscallRequest::RestartSyscall 119 -> 120 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3187
  variant SyscallRequest::SetITimer 120 -> 121 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3188
  variant SyscallRequest::GetITimer 121 -> 122 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3193
  variant SyscallRequest::Statx 122 -> 123 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3197
  variant SyscallRequest::TimerfdCreate 123 -> 124 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3204
  variant SyscallRequest::TimerfdSettime 124 -> 125 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3208
  variant SyscallRequest::TimerfdGettime 125 -> 126 in /home/runner/work/litebox/litebox/litebox_common_linux/src/lib.rs:3214

--- failure trait_method_added: pub trait method added ---

Description:
A non-sealed public trait added a new method without a default implementation, which breaks downstream implementations of the trait
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-item-no-default
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.51.0/src/lints/trait_method_added.ron

Failed in:
  trait method litebox_platform::time::Instant::saturating_add in file /home/runner/work/litebox/litebox/litebox_platform/src/time.rs:39

@CvvT
Weiteng Chen (CvvT) marked this pull request as ready for review October 30, 2026 19:28
@CvvT
Weiteng Chen (CvvT) added this pull request to the merge queue Oct 30, 2026
Merged via the queue into ulitebox with commit 9ab08f9 Oct 30, 2026
18 of 19 checks passed
@CvvT
Weiteng Chen (CvvT) deleted the weiteng/ulitebox-restart-poll-futex branch October 30, 2026 19:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant