mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Savestate: Keep pending adhocctl requests, so a waiting Init survives a load
With WLAN on and no server reachable, sceNetAdhocctlInit keeps its thread waiting for the login. The load dropped the request, and the wait ended in BUSY, which Init can't retry. Splinter Cell then ran its failure path with a deleted event flag. Also stop freeing matching event buffers into the restored allocator, and take the event lock when clearing. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
4bfaab058b
commit
639e57c2bd
2 files changed
+23
-5
No files matched your search
@@ -311,6 +311,7 @@ int NetAdhocPtp_Connect(int id, int timeout, int flag, bool allowForcedConnect =
|
||||
|
||||
// Forward declarations for the savestate mechanism (the matching is sadly not inside its own section)
|
||||
void deleteMatchingEvents(const int matchingId = -1);
|
||||
void discardMatchingEvents();
|
||||
void DoNetAdhocMatchingInited(PointerWrap &p);
|
||||
void DoNetAdhocMatchingThreads(PointerWrap &p);
|
||||
void ZeroNetAdhocMatchingThreads();
|
||||
@@ -510,7 +511,7 @@ static void __AdhocctlNotify(u64 userdata, int cyclesLate) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Socket not found?! Should never happen! But if it ever happened (ie. loaded from SaveState where adhocctlRequests got cleared) return BUSY and let the game try again.
|
||||
// Socket not found?! Should never happen! But if it ever happened (ie. loaded from an old SaveState, which didn't keep adhocctlRequests) return BUSY and let the game try again.
|
||||
if (adhocctlRequests.find(uid) == adhocctlRequests.end()) {
|
||||
WARN_LOG(Log::sceNet, "sceNetAdhocctl Socket WaitID(%i) not found!", uid);
|
||||
__KernelResumeThreadFromWait(threadID, SCE_NET_ADHOCCTL_ERROR_BUSY);
|
||||
@@ -1784,7 +1785,7 @@ int WaitBlockingAdhocSocket(u64 threadSocketId, int type, int pspSocketId, void*
|
||||
}
|
||||
|
||||
void __NetAdhocDoState(PointerWrap &p) {
|
||||
auto s = p.Section("sceNetAdhoc", 1, 8);
|
||||
auto s = p.Section("sceNetAdhoc", 1, 9);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
@@ -1864,15 +1865,27 @@ void __NetAdhocDoState(PointerWrap &p) {
|
||||
netAdhocGameModeEntered = false;
|
||||
netAdhocEnterGameModeTimeout = 15000000;
|
||||
}
|
||||
if (s >= 9) {
|
||||
// A thread may be waiting on one (sceNetAdhocctlInit waits for the login.) Without it, the
|
||||
// wait ends in an error, which for Init can't be retried: the library already counts as inited.
|
||||
Do(p, adhocctlRequests);
|
||||
if (p.mode == p.MODE_READ) {
|
||||
adhocctlStartTime = (u64)(time_now_d() * 1000000.0);
|
||||
}
|
||||
} else if (p.mode == p.MODE_READ) {
|
||||
adhocctlRequests.clear();
|
||||
}
|
||||
|
||||
if (p.mode == p.MODE_READ) {
|
||||
// Discard leftover events
|
||||
adhocctlEvents.clear();
|
||||
adhocctlRequests.clear();
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> adhocGuard(adhocEvtMtx);
|
||||
adhocctlEvents.clear();
|
||||
}
|
||||
adhocSocketRequests.clear();
|
||||
sendTargetPeers.clear();
|
||||
deleteAllAdhocSockets();
|
||||
deleteMatchingEvents();
|
||||
discardMatchingEvents();
|
||||
|
||||
// Let's not change "Inited" value when Loading SaveState to prevent memory & port leaks
|
||||
RestoreNetAdhocMatchingInited();
|
||||
|
||||
@@ -121,6 +121,11 @@ void deleteMatchingEvents(const int matchingId = -1) {
|
||||
}
|
||||
}
|
||||
|
||||
// For savestate loads: the events' buffers were allocated from the memory the load just replaced.
|
||||
void discardMatchingEvents() {
|
||||
std::lock_guard<std::recursive_mutex> adhocGuard(adhocEvtMtx);
|
||||
matchingEvents.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast Ping Message to other Matching Users
|
||||
|
||||
Reference in new issue
Block a user