Skip to content

test(libkernel): cover pthread_exit - #12078

Open
xXPBSXx wants to merge 2 commits into
boykopovar:mainfrom
xXPBSXx:test/posix-pthread-exit
Open

xXPBSXx wants to merge 2 commits into
boykopovar:mainfrom
xXPBSXx:test/posix-pthread-exit

Conversation

@xXPBSXx

@xXPBSXx xXPBSXx commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

What

Adds guest_posix_exit, a behaviour test for pthread_exit. The export forwards to scePthreadExit, which other tests cover, but no test called pthread_exit itself. The expected results come from FreeBSD 11.4 lib/libthr/thread/thr_exit.c (_pthread_exit and _pthread_exit_mask):

  • pthread_join returns the value passed to pthread_exit, and NULL when NULL is passed;
  • code after pthread_exit never runs;
  • a cleanup handler pushed by the thread runs once, and before the thread-specific data destructors;
  • a key destructor runs once and receives the stored value.

No production code changes. There is no failing arm on main: this is coverage of an existing export.

Tested

  • Windows 10 Pro, MinGW-w64 GCC 15.2, Release, head 0c844143cc on main d13b3d7c55 (ninja exit code 0): guest_posix_exit passes 3 of 3 runs (the longest run takes 0.6 s). The head before the rebase onto this main, 089c4d763b on main 14332cd8d0, passed 25 of 25 runs (5 plus 20 more as a check for flakiness; the longest run takes 0.85 s); the rebase did not touch the files of this PR.
  • Ubuntu 24.04 under WSL2 (a virtualised kernel, not bare-metal), GCC 13.3, Release, the same head 0c844143cc (ninja exit code 0): passes 3 of 3 runs (5 of 5 on 089c4d763b).
  • A second, independent measurement of this head, run by another session in a separate worktree on the same machine: on Windows guest_posix_exit passed 10 of 10 runs, and with pthread_exit passing nullptr it failed 3 of 3 runs at "join returns the value passed to pthread_exit"; on Ubuntu 24.04 under WSL2 (a virtualised kernel, not bare-metal) it passed 5 of 5 runs. The failing arm was not run on WSL2.
  • To see what the test catches, I changed the code on Windows six ways and built the test each time (ninja exit code 0); each change failed the test at the check named here and was reverted afterwards: pthread_exit passing nullptr (Pthread/Posix/Thread.cpp line 164; "join returns the value passed to pthread_exit"); pthread_exit returning without ending the thread (line 164; "code after pthread_exit never runs"); scePthreadExit without popping the cleanup handlers (Pthread/src/Thread.cpp line 1155; "the cleanup handler runs once on pthread_exit"); finishThread storing no return value (line 731; "join returns the value passed to pthread_exit"); the cleanup handlers popped after finishThread (lines 1155-1156; "the cleanup handler runs before the key destructor"); and the key destructors never run (Pthread/src/Tsd.cpp line 44; "the key destructor runs once on pthread_exit"). Removing the RunKeyDtors call in finishThread (line 728) does not fail the test, because the key destructors also run through Tsd.cpp.
  • check_conventions --base upstream/main passes, and git merge-tree against main d13b3d7c55 is clean.
  • Not run: macOS, a sanitizer build, pthread_exit on a host thread or the main thread.

Overlap

No open PR adds a test for pthread_exit; git grep on main finds no test that calls it. Of the 1358 open PRs, 70 change core/libs/prx/libkernel/CMakeLists.txt, Pthread/Posix/Thread.cpp, Pthread/src/Thread.cpp or this test. git merge-tree of the head before the rebase (on main 14332cd8d0; the rebase touched none of these files) with each of them conflicts for 25; 21 of those already conflict with main on their own. After main took the guest_posix_specific block, the test blocks of #11500, #10979, this PR and #11894 sit in different places in libkernel/CMakeLists.txt, and git merge-tree of each pair is clean (heads #11500 (b8685f7), #10979 (1a2cff7), #11894 (5a2d89e) and this head 1a00487af9); no landing order is needed.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

AI-assisted (Claude Code).

🤖 Generated with Claude Code

pthread_exit had no test, although scePthreadExit it forwards to is covered.
Check the FreeBSD 11.4 behaviour of _pthread_exit
(lib/libthr/thread/thr_exit.c lines 204-290): the value passed to
pthread_exit is returned by pthread_join (also NULL), code after the call
never runs, the cleanup handlers of the thread run once and before the
thread-specific data destructors, and a key destructor runs once with the
stored value.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

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 4563 core/libs/prx/libkernel/CMakeLists.txt
PR 5021 core/libs/prx/libkernel/CMakeLists.txt
PR 6936 core/libs/prx/libkernel/CMakeLists.txt
PR 7192 core/libs/prx/libkernel/CMakeLists.txt
PR 8477 core/libs/prx/libkernel/CMakeLists.txt
PR 9156 core/libs/prx/libkernel/CMakeLists.txt
PR 9293 core/libs/prx/libkernel/CMakeLists.txt
PR 9297 core/libs/prx/libkernel/CMakeLists.txt
PR 9302 core/libs/prx/libkernel/CMakeLists.txt
PR 9326 core/libs/prx/libkernel/CMakeLists.txt
PR 9383 core/libs/prx/libkernel/CMakeLists.txt
PR 9389 core/libs/prx/libkernel/CMakeLists.txt
PR 9557 core/libs/prx/libkernel/CMakeLists.txt
PR 9566 core/libs/prx/libkernel/CMakeLists.txt
PR 9938 core/libs/prx/libkernel/CMakeLists.txt
PR 10645 core/libs/prx/libkernel/CMakeLists.txt
PR 11002 core/libs/prx/libkernel/CMakeLists.txt
PR 11896 core/libs/prx/libkernel/CMakeLists.txt
PR 11939 core/libs/prx/libkernel/CMakeLists.txt
PR 12544 core/libs/prx/libkernel/CMakeLists.txt
PR 12682 core/libs/prx/libkernel/CMakeLists.txt
PR 12688 core/libs/prx/libkernel/CMakeLists.txt
PR 12700 core/libs/prx/libkernel/CMakeLists.txt
PR 12965 core/libs/prx/libkernel/CMakeLists.txt

@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.

Reviewed head 0c84414. The change is test-only and exercises the public pthread_exit wrapper through join result propagation (including nullptr), non-return, cleanup-handler execution/order, and key destructor value/count. I inspected the test and CMake registration; the 30-second timeout and Windows libkernel runtime PATH match neighboring guest tests. The exact PR head merges cleanly with current upstream/main, and the required stack (#11500, #10979, #11799, #11894) is open with clean merge states and the landing order is declared. GitHub Windows CI compiled/linked the test target but did not run CTest; Linux is skipped. I did not independently execute this test. The repeated Windows and WSL runs and mutation checks in the PR description are contributor-reported evidence, so this approval relies on that report plus source review, not on those runs being independently verified here.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 27, 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 28, 2026
@xXPBSXx

xXPBSXx commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

main is merged into the branch (head 1a00487af9): the conflict was in libkernel/CMakeLists.txt only, the test block of this PR now sits behind the guest_truncate_extend block, and the PR's commit is unchanged. The new test and its three neighbouring tests pass on Windows (4 of 4) and Linux (4 of 4) on the merge head.

AI-assisted (Claude Code).

@THEMANnt THEMANnt 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.

Reviewed 1a00487af998c6955c1fc7da55a8290b2e2a5665 against 6e9b9134f6ed14e659d870a33118d164096551df. The new pthread_exit fixture checks both null and non-null join values, nonreturning exit, a single cleanup handler followed by the TLS destructor, and the stored destructor argument. Each worker is joined before the global test context is reused. No actionable finding in this scoped test review.

Windows/GCC 15.3 Release: configured and built the registered target from pinned sources; focused CTest: 1 passed, 0 skipped. Checked that the fixture assertions remain active in Release. The added target is absent from the author base; no baseline runtime execution of that new fixture is claimed. Production source and the changed test-registration blocks were source-compared. Matching cached dependency source pins and the existing matching FFmpeg package are used. No game, physical-console or GPU validation is claimed.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants