Skip to content

Signal implement SYS_rt_sigtimedwait syscall 137#201

Open
doanbaotrung wants to merge 1 commit into
sysprog21:mainfrom
open-sources-port:SYS_rt_sigtimedwait
Open

Signal implement SYS_rt_sigtimedwait syscall 137#201
doanbaotrung wants to merge 1 commit into
sysprog21:mainfrom
open-sources-port:SYS_rt_sigtimedwait

Conversation

@doanbaotrung

@doanbaotrung doanbaotrung commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

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) so sigwait(3), sigwaitinfo(3), and sigtimedwait(3) work inside the guest. Adds the aarch64 ABI constant and wires the syscall through dispatch.

  • New Features
    • Adds SYS_rt_sigtimedwait = 137, registers sc_rt_sigtimedwait, and forwards args in syscall.c.
    • Dequeues one pending signal matching the mask; prefers thread-directed over process-directed.
    • Optional siginfo_t write; timeout supports block forever, poll once {0,0}, or bounded wait in 1 ms chunks.
    • Masks out SIGKILL/SIGSTOP. Returns signum on success, -EAGAIN on timeout, -EINTR on exit-group or unrelated unblocked signal.
    • Adds tests/test-sigtimedwait.c and a Makefile target (links -lpthread) covering sigwait, sigwaitinfo, poll-once, short timeout, and cross-thread delivery.
    • Updates scripts/check-syscall-coverage.py to map rt_sigtimedwait to sigwait, sigwaitinfo, and sigtimedwait.

Written for commit 0e6c431. Summary will update on new commits.

Review in cubic

@doanbaotrung doanbaotrung force-pushed the SYS_rt_sigtimedwait branch from 5b89e41 to 0e0f9a3 Compare July 13, 2026 14:23

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread src/syscall/signal.c
if (lts.tv_sec > (INT64_MAX / 1000000000LL))
remaining_ns = INT64_MAX;
else
remaining_ns = lts.tv_sec * 1000000000LL + lts.tv_nsec;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>

@doanbaotrung doanbaotrung force-pushed the SYS_rt_sigtimedwait branch 3 times, most recently from 72bafea to 6b3cf43 Compare July 13, 2026 15:25
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
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.

Implement SYS_rt_sigtimedwait to support synchronous signal handling sigwaitinfo/sigtimedwait

3 participants