Adhoc: Fix shutdown hanging when it comes right after adhoc init

The friend finder thread set friendFinderRunning itself, after a DNS
lookup of the adhoc server. A shutdown in that window cleared the flag
first; the thread then set it again, looped forever, and the join in
NetAdhocctl_Term() never returned. Gods Eater Burst hit this in about one
headless run in six. The flag is now set before the thread is created,
and a finished thread is joined before a new one replaces it, which
would otherwise call std::terminate.

The built-in adhoc server thread had the same race, behind its check for
an existing server, and gets the same fix.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-09-29 11:58:42 -06:00
1 parent 806618f9a3
commit 2cd84012d0
3 files changed
+14 -6

No files matched your search

+1 -2
View File
@@ -1401,8 +1401,7 @@ int friendFinder() {
}
g_adhocServerIP.in.sin_port = htons(SERVER_PORT);
// Finder Loop
friendFinderRunning = true;
// Finder Loop. The flag was set by whoever started us, and cleared to stop us.
while (friendFinderRunning) {
// Acquire Network Lock
//_acquireNetworkLock();
+1 -3
View File
@@ -1865,9 +1865,7 @@ int create_listen_socket(uint16_t port)
*/
int server_loop(int server)
{
// Set Running Status
//_status = 1;
adhocServerRunning = true;
// adhocServerRunning was set by whoever started the thread, and is cleared to stop it.
// Create Empty Status Logfile
update_status();
+12 -1
View File
@@ -1921,9 +1921,14 @@ void __NetAdhocInit() {
__AdhocNotifInit();
__AdhocServerInit();
// Create built-in AdhocServer Thread
// Create built-in AdhocServer Thread. The flag is set here rather than by the thread, so that a
// shutdown that clears it before the thread gets going can't be undone (see friendFinder).
adhocServerRunning = false;
if (adhocServerThread.joinable()) {
adhocServerThread.join();
}
if (g_Config.bEnableWlan && g_Config.bEnableAdhocServer) {
adhocServerRunning = true;
adhocServerThread = std::thread(proAdhocServerThread, SERVER_PORT);
}
}
@@ -2008,6 +2013,12 @@ int sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) {
// TODO: Merging friendFinder (real) thread to AdhocThread (fake) thread on PSP side
if (!friendFinderRunning) {
// Set before the thread starts, not by it: shutting down before it got going used to clear
// the flag first, and then the thread set it again and never stopped, hanging the join.
if (friendFinderThread.joinable()) {
friendFinderThread.join();
}
friendFinderRunning = true;
friendFinderThread = std::thread(friendFinder);
}