Skip to content

fix(libkernel): report the sender in the si_code of sigwaitinfo and sigtimedwait - #8497

Open
xXPBSXx wants to merge 6 commits into
boykopovar:mainfrom
xXPBSXx:fix/siginfo-sender-code
Open

xXPBSXx wants to merge 6 commits into
boykopovar:mainfrom
xXPBSXx:fix/siginfo-sender-code

Conversation

@xXPBSXx

@xXPBSXx xXPBSXx commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

What

The guest queue of pending signals kept only a bit per signal, and FillSiginfo always wrote si_code 0 (and the caller's pid). FreeBSD 11.4 stamps the signal with the sender: kill with SI_USER (0x10001, sys/kern/kern_sig.c:1788), thr_kill (so raise and pthread_kill) with SI_LWP (0x10007, kern_thr.c:401, lib/libc/gen/raise.c:52), and the interval-timer expiry with SI_KERNEL (0x10006) and pid 0 (kern_time.c:899, kern_sig.c:2087). Each pending signal now stores its code when it is marked, and sigwaitinfo/sigtimedwait return it. The expectations in guest_sigtimedwait that pinned 0 change accordingly.
Fixes #8496
The expectations of guest_sigtimedwait that #4138 set to 0 change here; #4138 took the siginfo_t layout from FreeBSD 11 and did not measure si_code on a console, as far as its description says. Overlap: git merge-tree is clean for #8407, #8411, #8414 and #8467, and has conflicts with #3986 (3), #6044 (26) and #7201 (25). pr_overlap was not run.

A second commit takes the pending signal and its code together. WaitForPendingInSet cleared the pending bit under pending.lock, but FillSiginfo read the code after the lock was released, so a second sender could overwrite the code in between and the wait reported the later sender for the signal it had already consumed (review of 23 October). PendingInSet now returns the code together with the signal under the lock, and FillSiginfo takes it as an argument. The rebase onto f26434afa3 changed only type names (GuestTimespec is KernelTimespec after #10706), one declaration in the test and the signature of WaitForPendingInSet; the logic is unchanged.

Tested

Base main f26434afa3, head 09605fb4ad (two commits). One checkout and build directory per platform; for the "old" arm only System/src/Signals.cpp is taken back to the first commit (the code is read after the lock is released), the tests of the head are kept. Each build's ninja exit code 0 was read.

  • Linux (WSL2 Ubuntu 24.04: a virtualised kernel, not bare-metal; GCC 13.3, Release), guest_sigtimedwait_tests run directly, 20 runs per arm: with the change 20 of 20 pass; with the old Signals.cpp 0 of 20 pass (all abort).
  • Windows 10 (19045), MinGW-w64 GCC 15.2.0, Release, ctest -R '^guest_sigtimedwait$', 10 runs per arm: with the change 10 of 10 pass. The old code also passes 10 of 10 in this run (0 of 10 failed), so on Windows the test does not reliably catch the race.
  • The new case (CheckReportedCodeBelongsToConsumedSignal) sends the same signal with kill and then with pthread_kill in each of 300 rounds; the wait may only report the pthread_kill code once, or the kill code followed by the pthread_kill code. There is no deterministic hook between releasing the lock and reading the code, so it is a stress test.
  • python tools/check_conventions.py --base upstream/main passes; git merge-tree against main f26434afa3 is clean.
  • Not tested: macOS, the hosted Windows configuration. The other signal tests listed for the first commit (guest_signals, guest_itimer, ...) were run on the earlier base cabd80f472 and are not repeated here.

Checklist

AI-assisted (Claude Code).

🤖 Generated with Claude Code

@github-actions github-actions Bot added the fix error Closes an issue (Fixes #N) label Oct 20, 2026
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 11002 docs/dev/debt/libkernel.md L309-310

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 3986 core/libs/prx/libkernel/System/src/Signals.cpp
PR 4630 docs/dev/debt/libkernel.md
PR 5021 docs/dev/debt/libkernel.md
PR 6740 docs/dev/debt/libkernel.md
PR 6936 docs/dev/debt/libkernel.md
PR 7088 docs/dev/debt/libkernel.md
PR 7105 docs/dev/debt/libkernel.md
PR 7121 docs/dev/debt/libkernel.md
PR 7135 docs/dev/debt/libkernel.md
PR 7149 docs/dev/debt/libkernel.md
PR 7192 docs/dev/debt/libkernel.md
PR 7447 docs/dev/debt/libkernel.md
PR 7464 docs/dev/debt/libkernel.md
PR 7804 docs/dev/debt/libkernel.md
PR 9156 docs/dev/debt/libkernel.md
PR 9199 docs/dev/debt/libkernel.md
PR 9293 docs/dev/debt/libkernel.md
PR 9297 docs/dev/debt/libkernel.md
PR 9302 docs/dev/debt/libkernel.md
PR 9389 core/libs/prx/libkernel/System/src/Signals.cpp
docs/dev/debt/libkernel.md
PR 9557 docs/dev/debt/libkernel.md
PR 9566 docs/dev/debt/libkernel.md
PR 9843 docs/dev/debt/libkernel.md
PR 9938 docs/dev/debt/libkernel.md
PR 10025 docs/dev/debt/libkernel.md
PR 10319 docs/dev/debt/libkernel.md
PR 10442 docs/dev/debt/libkernel.md
PR 11896 docs/dev/debt/libkernel.md
PR 11939 docs/dev/debt/libkernel.md
PR 12104 docs/dev/debt/libkernel.md
PR 12560 docs/dev/debt/libkernel.md
PR 12682 core/libs/prx/libkernel/System/src/Signals.cpp
docs/dev/debt/libkernel.md
PR 12688 core/libs/prx/libkernel/System/src/Signals.cpp
docs/dev/debt/libkernel.md
PR 12700 core/libs/prx/libkernel/System/src/Signals.cpp
docs/dev/debt/libkernel.md
PR 12965 core/libs/prx/libkernel/System/src/Signals.cpp
docs/dev/debt/libkernel.md
PR 12970 docs/dev/debt/libkernel.md
PR 13560 docs/dev/debt/libkernel.md
PR 14103 docs/dev/debt/libkernel.md
PR 14128 docs/dev/debt/libkernel.md
PR 14212 docs/dev/debt/libkernel.md
PR 14264 docs/dev/debt/libkernel.md
PR 14310 docs/dev/debt/libkernel.md
PR 14832 docs/dev/debt/libkernel.md
PR 14854 docs/dev/debt/libkernel.md
PR 14886 core/libs/prx/libkernel/System/src/Signals.cpp
docs/dev/debt/libkernel.md
PR 14894 docs/dev/debt/libkernel.md

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The signal code can race with a second sender after the wait has consumed the pending bit. WaitForPendingInSet holds pending.lock while PendingInSet clears the bit, then returns and releases the lock; sigwaitinfo/sigtimedwait call FillSiginfo afterward, which loads Pending().codes[guest]. If another thread queues the same signal in that gap, MarkPending overwrites the code and the waiter reports the later sender for the signal it already consumed. The current tests use one sender at a time, so they do not cover this interleaving.

Please capture the code together with consuming the pending signal while holding pending.lock (for example, have PendingInSet return both the signal and its code), then pass that captured value to FillSiginfo. Add a focused concurrent regression if practical. I have not run this branch locally; conventions and eligibility pass, while product jobs are skipped by the current workflow.

@xXPBSXx

xXPBSXx commented Oct 24, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, you are right: WaitForPendingInSet cleared the pending bit under pending.lock, but FillSiginfo read Pending().codes[guest] after the lock was released, so a second sender could overwrite the code in between and the wait reported the later sender for the signal it had already consumed.
PendingInSet now returns the code together with the signal under the lock, and FillSiginfo takes it as an argument. I added a test where one thread sends the same signal with kill and then with pthread_kill in each round (300 rounds); the wait may only report the pthread_kill code once, or the kill code followed by the pthread_kill code. With the old Signals.cpp it fails 20 of 20 runs on Linux (WSL2) with first=0x10007 second=0x10007, and passes 20 of 20 with the change. On Windows 10 it passes 10 of 10 with the change, but fails only 0 to 2 of 10 runs with the old code in two independent runs, so there it does not reliably catch the race. Both arms ran on the PR head e5a98fc (merge base with main cabd80f). Not tested: macOS.

AI-assisted (Claude Code).

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 24, 2026
@xXPBSXx
xXPBSXx force-pushed the fix/siginfo-sender-code branch from 2b68296 to c46fb47 Compare October 24, 2026 15:33
@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Oct 24, 2026
@xXPBSXx
xXPBSXx force-pushed the fix/siginfo-sender-code branch from c46fb47 to 09605fb Compare October 24, 2026 23:30
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 24, 2026

@ahmadmuj ahmadmuj left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Checked head 09605fb (base f26434a; also merges clean onto main 0119103).

What I ran, Linux (WSL2 Ubuntu 24.04, GCC 13.3, Release), guest_sigtimedwait 20 runs per arm, head test kept in every arm:

  • head: 20/20 pass
  • main's Signals.cpp: 0/20
  • first commit's Signals.cpp (9a3c3ee): 14/20 pass, so here the race case only catches the old code some of the time

The CR fix looks right to me: codes[] is only written in MarkPending and read in PendingInSet, both under pending.lock, so the code always goes with the bit that was taken.

Three things, checked against FreeBSD release/11.4.0:

1. The new race test pins coalescing that FreeBSD doesn't do. sigqueue_add allocates one ksiginfo per send, standard signals too (kern_sig.c:403-414), and sigqueue_get keeps the bit while another one is queued (kern_sig.c:330-335). kill lands on p_sigqueue (pksignal -> tdsendsignal(p, NULL), kern_sig.c:2168), thr_kill on td_sigqueue (kern_sig.c:2170), and kern_sigtimedwait takes the thread queue first (kern_sig.c:1286-1287). So when both sends land before the wait, FreeBSD gives two waits, 0x10007 then 0x10001. The twice branch requires the opposite order, and the once branch only happens with coalescing.

Probe on the head, signal 2 blocked, both sends first, then poll until EAGAIN:

Sends Head FreeBSD 11.4 (from the source)
raise, raise 0x10007, 1 wait 0x10007, 0x10007
kill, pthread_kill(self) 0x10007, 1 wait 0x10007, 0x10001
pthread_kill(self), kill 0x10001, 1 wait 0x10007, 0x10001

The single bit is older than this PR, so a real queue can be a follow-up. But then the test shouldn't lock in the one-slot result, and last-sender-wins belongs in the debt entry. For example twice ? first.code != second.code : first.code == 0x10007 still fails on the old race (it showed up as 0x10007 twice) and accepts both FreeBSD orders.

2. sendCode leaks into sends from a handler that kill runs inline. kill -> raise_nid_postfix -> DeliverPendingSignal calls the guest handler while sendCode is still SI_USER (a host signal through std::raise -> Dispatch does the same). So a raise of a blocked signal inside that handler gets SI_USER. Probe: SIGUSR2 blocked, the SIGUSR1 handler calls raise(SIGUSR2), then kill(getpid(), SIGUSR1). sigtimedwait on SIGUSR2 reports 0x10001; FreeBSD gives SI_LWP (thr_kill, kern_thr.c:401). A siglongjmp out of that handler also skips ~SentByKill, and then every later raise on that thread reports SI_USER. Passing the code down explicitly fixes both: an internal raise that takes the code, and MarkPending with no default.

3. The debt entry is stale. The sigtimedwait entry in docs/dev/debt/libkernel.md still says only si_code (SI_USER) is written. CONTRIBUTING asks to cut it to what's still open, so: per-send queuing and last sender wins.

Not checked: Windows, macOS, a console. The codes come from the FreeBSD source only.

@xXPBSXx
xXPBSXx force-pushed the fix/siginfo-sender-code branch from 09605fb to f9cc8ae Compare October 25, 2026 17:40
@xXPBSXx

xXPBSXx commented Oct 25, 2026

Copy link
Copy Markdown
Contributor Author

Thank you for the careful review and for measuring the earlier commit separately. I read the FreeBSD 11.4 sources for all three points, reproduced them with a probe on head 09605fb (Windows 10, MinGW-w64 GCC 15.2.0), and pushed a follow-up commit; the branch is rebased onto main 2e1c72239b (head f9cc8aec75, three commits; the first two are unchanged, git range-diff shows them as equal).

  1. Coalescing: you are right. sigqueue_add allocates one entry per send for ordinary signals (kern_sig.c:372-414; only SIGKILL/SIGSTOP take the bit-only path), sigqueue_get keeps the bit while another entry is queued (kern_sig.c:330-335), and kern_sigtimedwait takes the thread queue first (kern_sig.c:1286-1287). The probe on the old head matches your table: raise,raise and kill,pthread_kill(self) give one wait with 0x10007, pthread_kill(self),kill gives one wait with 0x10001. The test now uses your condition (twice ? first.code != second.code : first.code == 0x10007), and the debt entry says that a number holds one pending entry and the last sender wins. A queue per send is left for a follow-up.
  2. sendCode: you are right. On the old head kill(SIGUSR1) whose handler calls raise(SIGUSR2) reports 0x10001 for SIGUSR2, where FreeBSD gives 0x10007 (kern_thr.c:401); after a longjmp out of such a handler, a later plain raise on the thread also reported 0x10001. The follow-up removes the thread-local code: raise and kill share one internal raise that takes the code, and MarkPending has no default. All probe cases now report 0x10007. The new check in guest_sigtimedwait covers both the handler and the longjmp case.
  3. Debt entry: updated to the current behaviour and to what is still open (one pending entry per signal number, last sender wins; SI_USER for kill, SI_LWP for raise and pthread_kill). The entry was already over the length limit before this change and still is (the conventions check reports it as a warning); I did not cut the older parts of it here.

Measured on head f9cc8aec75, ninja exit code 0 read for every build: Windows 10 (MinGW-w64 GCC 15.2.0), guest_sigtimedwait 10 of 10 pass; with Signals.cpp of the previous commit and the new test kept, 0 of 5 pass. Linux (WSL2 Ubuntu 24.04, GCC 13.3), 20 of 20 pass; with the previous Signals.cpp, 0 of 20. tools/check_conventions.py --base upstream/main reports no errors; git merge-tree against main is clean. Not measured: the changed race condition on its own against the old race (the old arms fail on the new check as a whole), macOS; the codes come from the FreeBSD source.

AI-assisted (Claude Code).

xXPBSXx and others added 3 commits October 25, 2026 22:29
…igtimedwait

FreeBSD 11.4 stamps the queued signal with the sender: kill() uses SI_USER
0x10001 (sys/kern/kern_sig.c:1788), thr_kill, and so raise and pthread_kill,
use SI_LWP 0x10007 (kern_thr.c:401, lib/libc/gen/raise.c:52), and the
SIGALRM expiry of an interval timer comes from kern_psignal with SI_KERNEL
0x10006 and pid 0 (kern_time.c:899, kern_sig.c:2087; values in
sys/sys/signal.h:400-409). The guest reported si_code 0 for all of them.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…and sigtimedwait

WaitForPendingInSet cleared the pending bit under pending.lock, but FillSiginfo read the code after the lock was released. A second sender could overwrite the code in between, so the wait reported the later sender for the signal it had already consumed. PendingInSet now returns the code together with the signal, under the lock, and FillSiginfo takes it as an argument. The test sends the same signal with kill and pthread_kill in each round and checks that the two reported codes never repeat the later sender.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@xXPBSXx
xXPBSXx force-pushed the fix/siginfo-sender-code branch from f9cc8ae to 92a7a10 Compare October 25, 2026 21:41
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 25, 2026
@xXPBSXx

xXPBSXx commented Oct 25, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto main 90f918fa71 (new head 92a7a10ce3), no change to the fix. main gained DeliverUnblockedPending in Signals.cpp right above WaitForPendingInSet; the only conflict was the new signature of WaitForPendingInSet. The four callers of MarkPending on main (blocked host signal, SIGALRM, raise/kill, pthread_kill) are the ones this branch already passes a code to, so no code changed: host signals and pthread_kill keep SI_LWP, the timer's SIGALRM keeps SI_KERNEL.

Ninja exit code 0 read for every build. Windows 10: guest_sigtimedwait 10 of 10 pass, 0 of 5 with Signals.cpp of the previous commit; guest_signals, guest_signal_interrupt, guest_signal_handler_mask and guest_signal_sets pass. Linux (WSL2): guest_sigtimedwait 20 of 20 pass, 0 of 20 with the previous Signals.cpp; the four other signal tests pass. git merge-tree against current main 88f99678bf is clean.

AI-assisted (Claude Code).

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 26, 2026
@xXPBSXx

xXPBSXx commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

Merged main (88795ed448) into the branch; head 5222418127. Two merged pull requests (#11167 and the pselect change) touched the same wait loop and test file, so I kept both sides: the wait loop and CheckShortTimeouts from main, and the code argument to PendingInSet plus the two sender-code checks from this branch; the patch lines of this PR are unchanged. guest_sigtimedwait passes 3 of 3 runs on Windows 10 and on Ubuntu 24.04 under WSL2 (a virtualised kernel, not bare-metal), GCC 13.3, and fails 3 of 3 with Signals.cpp taken back to main (ninja exit code 0 for every build).

AI-assisted (Claude Code).

@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Oct 26, 2026
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 31, 2026
@xXPBSXx

xXPBSXx commented Oct 31, 2026

Copy link
Copy Markdown
Contributor Author

Merged main (18f594978831) into this branch; the merge commit is 096bf086a7 and the previous head was 5222418127.

Two files conflicted. In Signals.cpp, main now copies the signal set, the timeout and the siginfo result through the guest-memory helpers and answers EFAULT for an unusable pointer; I kept that and kept this PR's si_code handling, so FillSiginfo takes the code, builds the record locally and copies it out, and sigtimedwait and sigwaitinfo hand the code that WaitForPendingInSet returns to it (sigwait ignores it). In GuestSigtimedwait.cpp both sets of checks stay: this PR's si_code checks and the EFAULT checks from main.

main is now 25 commits ahead of that merge (0f6143fecf); one of them touches docs/dev/debt/libkernel.md (03a4bd851e, a different entry), and git merge-tree of the merge head with it is clean (checked 2026-10-31 06:49 UTC).

Tested on the merge head (Windows 10, MinGW-w64 GCC, Release): guest_sigtimedwait, guest_signals, guest_signal_interrupt, guest_signal_handler_mask, guest_signal_sets, guest_sigaltstack and guest_signal_list pass, 7 of 7. With FillSiginfo changed to always report GuestSiUser, guest_sigtimedwait aborts. Not run: Linux, macOS.

AI-assisted (Claude Code).

@bunbeans2-arch

Copy link
Copy Markdown
Contributor

A Windows run with GCC 16: Windows 10.0.22631 (Windows 11), i9-9900K, MSYS2 UCRT64 GCC 16.1.0 (Rev5), Release, this PR (096bf086a7) merged into main 88e804b0a7.

Repro for #8496: this PR's guest_sigtimedwait, whose new checks expect si_code 0x10001 for kill, 0x10007 for raise/pthread_kill and 0x10006 for the timer.

  • ❌ Before: same tree with only Signals.cpp put back to main. It failed in 5 of 5 runs: a check failed and the test aborted (FATAL: abort() (SIGABRT), exit 0xc0000409), as the issue says it does before the fix. The test does not print which value it got.
  • ✅ After: with this PR it passed 5 of 5.

So sigwaitinfo and sigtimedwait now report the sender codes the test expects, as #8496 asks 👍

AI-assisted: yes (Claude Code)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 4, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head 81681f2 merged onto main 5b1d381 · tested 2026-11-04 13:37 UTC · 23 min

GPU AMD Radeon RX 6300 (RADV NAVI24), driver Mesa 25.2.8-0ubuntu0.24.04.4, Vulkan 1.4.318
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-42-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,968 passed · 8 failed (0 new, 7 also fail on main, 1 unstable on main) · 59 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 3,035 of 3,883 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (1060 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 121.0 s, ⚠️ agc_driver_image_sample_unnormalized 56.3 s, ⚠️ agc_driver_lazy_resolved_abi 48.5 s, ⚠️ agc_driver_sample_multisample_target 48.5 s, ⚠️ public_headers 36.9 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 8 of the last 10 main runs
Failing on main too (7, not counted against this PR)
agc_driver_image_table
agc_driver_native_depth_bda_clear
agc_driver_native_multisample_depth
agc_driver_submit_progress
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
Validation IDs already present on main (8 IDs in 622 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (622 tests): agc_driver, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, agc_driver_bda_span_reads, and 614 more
VUID-vkCmdCopyImage-srcImage-01548 (4 tests): agc_driver_depth_clear_hle, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (4 tests): agc_driver_depth_clear_hle, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
VUID-VkSamplerCreateInfo-addressModeU-01079 (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeU-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeV-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeW-parameter (1 test): agc_driver_image_gather_volume
Skipped (59)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_copied_writer_label_order: skipped, the device reports a minStorageBufferOffsetAlignment of 4, so the dispatch binds its record at +0x1004 in place and nothing is written back; the test needs an alignment above 4
agc_driver_float16_unused_nan_payloads: skipped, the device has no native f16 conversions with RTE rounding and kept f16 denormals
agc_driver_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_image_table_vouched_lookups: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a watched imported table cannot be vouched for
agc_driver_linear_target_direct_write_completion: skipped, the device does not keep host imports write-watched, so no completion stamp over the target is tracked
agc_driver_ngg_vertex_wave_reduction: skipped, s3 describes a 32-lane wave only on 32-lane subgroups, and the device has 64 lanes
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_driver_unit_shadow_budget: skipped, the device does not import watched host memory for unit shadows
agc_driver_vertex_elected_atomic_max: skipped, the device runs vertex programs in subgroups, so they keep their cross-lane reductions
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_idle_publish_wait: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a forced watch of the import reads its submissions as CPU stores
agc_shadowed_key_stores: skipped, the device imports no watched host memory under a unit shadow
agc_small_tiled_shadow_label: skipped, host imports are unavailable: the test block is not imported and watched
agc_storage_clear_hand_over: skipped, the device imports no watched host memory for the clear-key hand-over
agc_storage_pending_key_refresh: skipped, refreshes over a pending key store are not testable here
agc_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan 
Reproduce
git fetch origin 81681f240d67f8213a881a1d09801412a38cc31c 5b1d381d5ad5d9f923326b18479c3bd889cdd588
git checkout 5b1d381d5ad5d9f923326b18479c3bd889cdd588 && git merge --no-ff 81681f240d67f8213a881a1d09801412a38cc31c
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 12 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 16 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@xXPBSXx

xXPBSXx commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

What

Merged main (1e658521a0a599872612bb91949311e2956b5283) into this branch because it conflicted. The merge commit is 81681f240d67f8213a881a1d09801412a38cc31c, with the previous head 096bf086a71de5f0f1dc6e07cbc517410834d40c as its first parent.

The only conflict was the sigtimedwait entry in docs/dev/debt/libkernel.md: main changed its SIGPIPE sentence (the Linux guest 13 wording), and this PR changed the pending-entry and si_code sentences. Both sets of edits are kept. Signals.cpp and the test merged without a conflict. Against main the change is the same three files as before: Signals.cpp, GuestSigtimedwait.cpp and docs/dev/debt/libkernel.md, 118 insertions and 25 deletions.

The change request from 2026-10-23 about the sender code racing with a second sender is answered by the commit that takes the signal and its code together in sigwaitinfo and sigtimedwait, which this branch already contained.

Tested

  • Ubuntu 24.04, GCC 13.3, Linux, guest_sigtimedwait, 17:35 UTC to 17:38 UTC on 2026-11-03, on the merge commit.
  • With the merge commit: Passed in 5 of 5 runs.
  • Signals.cpp from main, test unchanged: the test aborted in 5 of 5 runs.
  • Signals.cpp restored: Passed in 5 of 5 runs. cmake and ninja exited 0 in every arm.
  • python -I tools/check_conventions.py --base 1e658521a0a599872612bb91949311e2956b5283 reported 0 errors and one warning at 17:42 UTC on 2026-11-03: the sigtimedwait debt entry is over 1000 characters (2639 now; 2330 on main). git diff --check is clean.
  • Not run: Windows and macOS in this session.

Overlap

Checked against main 1e65852 with the 1738 open PRs listed at 17:41 UTC on 2026-11-03 (scan from 17:39 UTC to 18:19 UTC); the changed files of each PR come from git diff --name-only against its merge base. 102 PRs change Signals.cpp, GuestSigtimedwait.cpp or docs/dev/debt/libkernel.md. Measured against this head with git merge-tree: 62 are clean. The other 40 also conflict with main alone, so this merge does not cause any of them. Against current main b11c7bf84f (checked on 2026-11-04 at 13:18 UTC) the merge is clean. Depends on: none.

AI-assisted (Claude Code).

@github-actions github-actions Bot added the docs label Nov 5, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs fix error Closes an issue (Fixes #N) libkernel

Projects

None yet

Development

Successfully merging this pull request may close these issues.

libkernel: sigwaitinfo and sigtimedwait report si_code 0 for every signal; FreeBSD 11.4 reports the sender

6 participants