Signal implement SYS_rt_sigtimedwait syscall 137#201
Conversation
5b89e41 to
0e0f9a3
Compare
There was a problem hiding this comment.
1 issue found and verified against the latest diff
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/syscall/signal.c">
<violation number="1" location="src/syscall/signal.c:1419">
P2: The saturation check uses `>` instead of `>=`, so a guest-supplied timespec with tv_sec == INT64_MAX/1000000000 and a large tv_nsec can make `tv_sec * 1000000000LL + tv_nsec` exceed INT64_MAX, causing signed overflow (UB) rather than saturating to INT64_MAX.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| if (lts.tv_sec > (INT64_MAX / 1000000000LL)) | ||
| remaining_ns = INT64_MAX; | ||
| else | ||
| remaining_ns = lts.tv_sec * 1000000000LL + lts.tv_nsec; |
There was a problem hiding this comment.
P2: The saturation check uses > instead of >=, so a guest-supplied timespec with tv_sec == INT64_MAX/1000000000 and a large tv_nsec can make tv_sec * 1000000000LL + tv_nsec exceed INT64_MAX, causing signed overflow (UB) rather than saturating to INT64_MAX.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/syscall/signal.c, line 1419:
<comment>The saturation check uses `>` instead of `>=`, so a guest-supplied timespec with tv_sec == INT64_MAX/1000000000 and a large tv_nsec can make `tv_sec * 1000000000LL + tv_nsec` exceed INT64_MAX, causing signed overflow (UB) rather than saturating to INT64_MAX.</comment>
<file context>
@@ -1332,7 +1332,162 @@ int64_t signal_rt_sigpending(guest_t *g, uint64_t set_gva, uint64_t sigsetsize)
+ if (lts.tv_sec > (INT64_MAX / 1000000000LL))
+ remaining_ns = INT64_MAX;
+ else
+ remaining_ns = lts.tv_sec * 1000000000LL + lts.tv_nsec;
+ }
+
</file context>
6b3cf43 to
0e6c431
Compare
| uint64_t *blocked = thread_blocked_ptr(); | ||
| uint64_t deliverable; | ||
| pthread_mutex_lock(&sig_lock); | ||
| deliverable = self_pending_locked() & ~*blocked & ~mask; |
There was a problem hiding this comment.
signal_rt_sigtimedwait's EINTR check doesn't filter by signal disposition, so signals that should silently discard (SIG_IGN, or default-ignore/continue/stop like SIGCHLD/SIGURG/SIGWINCH/SIGCONT) spuriously wake the wait when they're not in mask
signal_pending_interruption() (signal.c:611) already implements the correct disposition filter. Suggest reusing that filtering logic here
There was a problem hiding this comment.
Thanks for the review.
Fixed. The old check used a raw bitmask self_pending_locked() & ~blocked & ~mask which would spuriously wake the wait for signals like SIGCHLD, SIGURG, SIGWINCH, and SIGCONT — all of which are silently discarded by signal_deliver with no guest-visible effect.
Replaced it with a disposition-aware filter loop that mirrors signal_pending_interruption() exactly: a candidate signal only causes -EINTR if it has a real user-visible effect — an explicit non-SIG_IGN handler, or a SIG_DFL disposition of TERM/CORE. Signals with SIG_IGN or default IGN/CONT/STOP dispositions now correctly fall through and do not interrupt the wait.
0e6c431 to
5bd358c
Compare
Add rt_sigtimedwait so that sigwait(3), sigwaitinfo(3), and
sigtimedwait(3) work inside the guest. All three are thin wrappers
over this syscall in musl and glibc; returning -ENOSYS breaks any
application that uses a dedicated signal-management thread.
abi.h:
Define SYS_rt_sigtimedwait = 137, which sits between
rt_sigpending (136) and rt_sigqueueinfo (138) in the aarch64
Linux syscall table.
signal.c:
sigtimedwait_try_dequeue() - acquires sig_lock and dequeues one
signal matching the caller's mask. Thread-directed (private)
set is drained before the shared set, mirroring Linux
dequeue_signal() priority. Reuses signal_rt_dequeue_locked()
and signal_standard_peek_locked() from signal_deliver().
signal_rt_sigtimedwait() - reads and validates the guest mask
and optional timeout, then polls in 1 ms sleep chunks (same
pattern as interruptible_sleep_ns in time.c) until:
- a matching signal is consumed -> return signum
- timeout expires -> return -EAGAIN
- exit_group requested -> return -EINTR
- unblocked non-waited signal -> return -EINTR
SIGKILL/SIGSTOP are silently removed from the wait mask,
matching Linux do_sigtimedwait behavior.
NULL timeout_gva blocks indefinitely; {0,0} polls once.
info_gva = 0 skips the siginfo_t write (sigwait(3) path).
signal.h: declare signal_rt_sigtimedwait.
dispatch.tbl: register sc_rt_sigtimedwait with guest-ptr flag.
syscall.c: SC_FORWARD x0..x3 -> set, info, timeout, sigsetsize.
Fix sysprog21#196
5bd358c to
c749b7a
Compare
Add rt_sigtimedwait so that sigwait(3), sigwaitinfo(3), and sigtimedwait(3) work inside the guest. All three are thin wrappers over this syscall in musl and glibc; returning -ENOSYS breaks any application that uses a dedicated signal-management thread.
abi.h:
Define SYS_rt_sigtimedwait = 137, which sits between
rt_sigpending (136) and rt_sigqueueinfo (138) in the aarch64
Linux syscall table.
signal.c:
sigtimedwait_try_dequeue() - acquires sig_lock and dequeues one
signal matching the caller's mask. Thread-directed (private)
set is drained before the shared set, mirroring Linux
dequeue_signal() priority. Reuses signal_rt_dequeue_locked()
and signal_standard_peek_locked() from signal_deliver().
signal_rt_sigtimedwait() - reads and validates the guest mask
and optional timeout, then polls in 1 ms sleep chunks (same
pattern as interruptible_sleep_ns in time.c) until:
- a matching signal is consumed -> return signum
- timeout expires -> return -EAGAIN
- exit_group requested -> return -EINTR
- unblocked non-waited signal -> return -EINTR
SIGKILL/SIGSTOP are silently removed from the wait mask,
matching Linux do_sigtimedwait behavior.
NULL timeout_gva blocks indefinitely; {0,0} polls once.
info_gva = 0 skips the siginfo_t write (sigwait(3) path).
signal.h: declare signal_rt_sigtimedwait.
dispatch.tbl: register sc_rt_sigtimedwait with guest-ptr flag.
syscall.c: SC_FORWARD x0..x3 -> set, info, timeout, sigsetsize.
Fix #196
Summary by cubic
Implements
SYS_rt_sigtimedwait(137) sosigwait(3),sigwaitinfo(3), andsigtimedwait(3)work inside the guest, matching Linux behavior and unblocking apps with a signal-manager thread.SYS_rt_sigtimedwait: defines 137, registerssc_rt_sigtimedwait, forwards args, and updates coverage mapping (sigwait,sigwaitinfo,sigtimedwait).siginfo_t; masksSIGKILL/SIGSTOP;NULLtimeout blocks,{0,0}polls once, finite waits in 1 ms chunks; returns signum on success,-EAGAINon timeout,-EINTRon exit-group or an unblocked deliverable unrelated signal.tests/test-sigtimedwait.cand a Makefile target (links-lpthread) coveringsigwait,sigwaitinfowithsiginfo_t, zero-time poll, short timeout, and cross-thread delivery.Written for commit c749b7a. Summary will update on new commits.