Repository navigation
fix(libSceNpTrophy): keep a trophy locked when its unlock state cannot be saved - #12290
Conversation
…t be saved sceNpTrophyUnlockTrophy inserted the id into the in-memory set and then saved the state file. A save that threw (the state directory or the rename failed) left the trophy unlocked in memory but not on disk, so a retry answered TROPHY_ALREADY_UNLOCKED and the unlock was lost at the next start. The new set is now built on a copy, written, and only then installed. SaveState also never looked at the stream after writing, so a failed write (for example a full disk) was ignored and the truncated temporary file was renamed over the good state file. It now flushes, checks the stream, removes the partial temporary file and throws.
A directory in place of the temporary state file makes the save fail; the unlock has to report it, leave trophy 0 locked, and succeed once the directory is gone.
|
Windows result for head Host: Windows 11 26300, Intel i7-12700K, WinLibs GCC 15.2.0 (x86_64-ucrt-posix-seh, r6), Release, The tree also carried the open PRs #12288, #12285, #12269, #12265, #12232, #12206, #12201, #12199, #12197, #12165, #12146, all merged cleanly, so the run is a joint one; the tests of this PR are AI-assisted: yes (Claude Code), the runs and the numbers above are from this machine. |
|
Results in the project's real build on Windows and Linux, with the control the description lists as not run ("I did not run the new assertions against the unfixed code"). Head Windows: Windows 11 Pro 26300, AMD Ryzen 7 7800X3D, WinLibs GCC 15.2.0 r7, Ninja Release,
Linux: Ubuntu 22.04 under WSL2, GCC 11.4.0, Ninja Release.
Not tested: a real save-data failure outside the test's setup, macOS, any title. AI-assisted (Claude Code). |
What
sceNpTrophyUnlockTrophyinserted the trophy id into the in-memory set and then saved the state file. When the save threw (the state directory or the rename failed), the trophy stayed unlocked in memory but not on disk, so a retry answeredTROPHY_ALREADY_UNLOCKEDand the unlock was lost at the next start. The new set is now built on a copy, written, and only then installed.SaveStatealso never looked at the stream after writing, so a failed write (a full disk, for example) was ignored and the truncated temporary file was renamed over the good state file. It now flushes, checks the stream, removes the partial temporary file and throws, in the library's existing fail-loud style.Two commits: the fix, then the test (
GuestNpTrophy.cpp: a directory in place of the temporary state file makes the save fail; the unlock has to report it, leave trophy 0 locked, and succeed once the directory is gone).Tested
Linux x86-64, a throwaway archive build with the host CPU gate patched.
guest_np_trophypasses. I did not run the new assertions against the unfixed code.tools/check_conventions.py --base upstream/mainandgit diff --checkpass.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)