Repository navigation
feat(libc): implement alarm - #2765
Conversation
|
A second title stops at
The "with this PR" column comes from one build of AI-assisted (Claude Code). |
adriadam10
left a comment
There was a problem hiding this comment.
Thanks, alarm is a real next stop for RetroArch/Porpoise. One blocker, found on Linux:
guest_signalshangs on Linux (killed after 455 s by ctest); onmainit passes. All checks finish, then the process never exits.alarmLock/alarmChangedare function-local-namespace statics, andRunAlarmsis a detached thread parked inalarmChanged.wait(lock)(core/libs/prx/libkernel/System/src/Signals.cpp:109). At exit the staticstd::condition_variableis destroyed with a waiter still on it, and glibc'spthread_cond_destroyblocks forever. A 10-line program with a detached thread waiting on a global condition variable reproduces it. MinGW doesn't block there, which is why it passed on your machine. This would also hang any guest process that callsalarmand then exits normally.
Fix: don't destroy the state at exit (e.g. heap-allocate the mutex/condition variable/deadline and leak them), or make the thread stoppable and joined; then rerunguest_signalson Linux.- Once rebased: #3047 also edits the includes of
Signals.cpp(lines 7-8); whichever lands second needs a trivial rebase.
The rest matches FreeBSD's alarm.c (round-up remaining seconds, alarm(0) cancels) and the new test pins those values.
|
Linux check, since this was only run on Windows: 018097e merged onto
That fits static destruction: |
RetroArch (PPSA99169) stops at alarm on main: `FAIL: unresolved ELF import DQXJraCc1rA from libSceLibcInternal.prx`. alarm(seconds) arms one process-wide real-time alarm and returns the seconds left on the previous one, rounded up like FreeBSD's alarm.c (any partial second counts); alarm(0) cancels it. When it expires, SIGALRM's disposition as recorded by sigaction or signal applies: ignored, nothing happens; default, the process terminates as on FreeBSD (exit status 128 + 14); a guest handler throws, because asynchronous delivery to a guest handler is not implemented. The timer lives in libkernel next to the signal dispositions (GuestAlarm_nid_no_patch); libSceLibcInternal, which the titles import alarm from, forwards to it. AI-assisted (Claude Code). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The detached alarm thread waits on a condition variable that was a namespace-scope static. At exit its destructor ran with the thread still waiting, and glibc's pthread_cond_destroy blocks then, so a process that called alarm never exited on Linux. The mutex, condition variable, deadline and started flag now live in one structure allocated once and never destroyed. AI-assisted (Claude Code). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
018097e to
e5ae8df
Compare
|
Thanks @adriadam10 and @babyhuey for running it on Linux. Fixed in e5ae8df:
I also rebased onto current
AI-assisted (Claude Code). |
adriadam10
left a comment
There was a problem hiding this comment.
Checked on Linux: build and guest_signals pass on the merge with main (and fail to link without the change); the exit hang is gone, also confirmed by @babyhuey on Ubuntu. alarm semantics match FreeBSD alarm.c (rounding up partial seconds, 0 cancels), and the unmodelled guest-handler path throws. Merging.
What
RetroArch (PPSA99169) stops at
alarmon currentmain:This implements it, following FreeBSD.
alarm(seconds)arms one process-wide real-time alarm and returns the seconds left on the previous one. Any partial second counts, as in FreeBSD'salarm.c, which adds one whenit_value.tv_usecis non-zero.alarm(0)cancels the pending alarm.sigaction/signalapplies:alarm: delivering SIGALRM to a guest handler is not implemented, because the signal layer has no asynchronous delivery to a guest handler yet.GuestAlarm_nid_no_patch). libSceLibcInternal, which titles importalarmfrom, forwards to it.Tested
Windows 11 Pro (26200), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release.
guest_signal_tests:alarm(0)with nothing pending returns 0; arming 5 and then re-arming 3 returns 5; cancelling returns 3, then 0. With SIGALRM ignored, a 1-second alarm expires during a 1.5 s sleep without ending the process, and nothing is left pending.maincf8b129: onmainit stops at the line above. With this branch it gets pastalarmand stops atFAIL: unresolved ELF import E4wZaG1zSFc from libSceLibcInternal.prx(dirname, closed feat(libc): implement dirname #1761).maincf8b129. Full suite: 550 of 554 pass, 1 skipped.agc_driver_prepared_shaders_debug_failureandguest_memoryfail the same way on cleanmainon this machine.agc_driver_prepared_shadersfailed under the parallel run and passes alone (twice). It was run from the generatedCTestTestfile.cmakecommands because antivirus blocksctest.exeon this machine.tools/check_conventions.pypasses.The default-disposition and guest-handler paths end the process, so they have no in-process test. Not tested on Linux or macOS.
Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code