Skip to content

fix(libkernel): return ESRCH from signalto for a handle that is not a thread - #13832

Open
zaryabzip wants to merge 1 commit into
boykopovar:mainfrom
zaryabzip:fix/pthread-cond-signalto-esrch
Open

zaryabzip wants to merge 1 commit into
boykopovar:mainfrom
zaryabzip:fix/pthread-cond-signalto-esrch

Conversation

@zaryabzip

Copy link
Copy Markdown
Contributor

What

scePthreadCondSignalto and pthread_cond_signalto_np returned EPERM for a handle that is not a thread. A PS5 returns ESRCH there. @orezraey measured it in a payload process on firmware 13.60 (probe and log, from #11263):

Thread argument scePthreadCondSignalto pthread_cond_signalto_np main before
null 0x80020016 22 same
0x12345 0x80020003 3 0x80020001 / 1
a live thread that isn't waiting 0x80020001 1 same

The debt entry already recorded the difference. The new check sits between the null check and the not-waiting check, as the console orders them. It uses GuestThreadIsLive, the lookup pthread_getprio, sched_setparam and pthread_setaffinity_np already use to answer ESRCH. It compares the handle with the registered threads without dereferencing it. A thread that has finished but hasn't been joined wasn't tried on the console; like those calls, it now gets ESRCH here, and the debt entry says so. No function changes count.

GuestCondTimedwait.cpp's SignalTo() adds the 0x12345 case for both exports. Its existing checks still require EPERM for the calling thread, which isn't waiting.

Overlap: #13725 also changes Cond.cpp and the debt line above, in other places; git merge-tree merges the two cleanly.

Tested

Windows 11 (WinLibs MinGW-w64 GCC 15.2.0 UCRT r7, CMake 4.3.1, Ninja 1.13.2) and Ubuntu 24.04 on WSL2 (GCC 13.3.0, CMake 3.28.3, Ninja 1.11.1), both with the head 0a5c3be merged into main e8c25dd.

  • No warnings in Cond.cpp or GuestCondTimedwait.cpp.
  • ctest -R "cond|pthread" -E "^agc_|^secondary_output": 69 of 69 pass on both hosts, covering the guest_cond_*, guest_pthread_*, guest_kernel_sys_pthread* and guest_ult_condition_* tests. guest_cond_timedwait passes 3 of 3 on --repeat until-fail:3. The existing checks that the calling thread gets EPERM still pass.
  • Baseline: on that main with only the test change, guest_cond_timedwait builds and then aborts at the first 0x12345 check (line 153), where main returns EPERM (Windows exit 0xc0000409, Linux SIGABRT).
  • tools/check_conventions.py passes.

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 (Claude Code)

… thread

scePthreadCondSignalto and pthread_cond_signalto_np answered EPERM for a
handle that is not a live thread, where a PS5 on firmware 13.60 returns
ESRCH. The check sits between the null-thread and not-waiting checks, as
that console orders them.
@github-actions

github-actions Bot commented Oct 31, 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 4630 docs/dev/debt/libkernel.md
PR 5021 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 7509 docs/dev/debt/libkernel.md
PR 7804 docs/dev/debt/libkernel.md
PR 8605 docs/dev/debt/libkernel.md
PR 9156 docs/dev/debt/libkernel.md
PR 9199 docs/dev/debt/libkernel.md
PR 9242 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 9326 docs/dev/debt/libkernel.md
PR 9389 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 10442 docs/dev/debt/libkernel.md
PR 10558 docs/dev/debt/libkernel.md
PR 10645 docs/dev/debt/libkernel.md
PR 10789 docs/dev/debt/libkernel.md
PR 11002 docs/dev/debt/libkernel.md
PR 11215 docs/dev/debt/libkernel.md
PR 11939 docs/dev/debt/libkernel.md
PR 12688 docs/dev/debt/libkernel.md
PR 12700 docs/dev/debt/libkernel.md
PR 12925 docs/dev/debt/libkernel.md
PR 12965 docs/dev/debt/libkernel.md

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.

1 participant