fix(libc): end the process without detach routines in _Exit on Windows
On Windows std::_Exit ends in ExitProcess, which still runs every module's DLL_PROCESS_DETACH and TLS callbacks after the other threads are gone. A static destructor that joins a worker then waits forever: a title that calls _Exit while libSceVideoOut's flip queue runs (ps5-opengl's retirement fail-stop) stays alive in FlipQueue's destructor. _Exit and libkernel's _exit now terminate the process with TerminateProcess, as _exit ends a POSIX process: no atexit handlers, stream flushes or module destructors.
This commit is contained in:
parent
f6af6d11d3
commit
bc8587a6fe
|
|
@ -12,5 +12,6 @@ extern "C" void LibcRequestShutdown_nid_postfix();
|
|||
extern "C" void LibcRequestExit_nid_postfix(int code);
|
||||
extern "C" [[noreturn]] void LibcAwaitExit_nid_postfix();
|
||||
extern "C" [[noreturn]] void LibcExit_nid_no_patch(int code);
|
||||
extern "C" [[noreturn]] void LibcTerminate_nid_no_patch(int code);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <atomic>
|
||||
#include <stdexcept>
|
||||
#include "prx/libc/include/Shutdown.hpp"
|
||||
|
|
@ -106,6 +109,13 @@ extern "C" {
|
|||
std::fprintf(stderr, "[libc] _Exit(%d) called from %p\n", code, __builtin_return_address(0));
|
||||
std::fflush(stderr);
|
||||
}
|
||||
LibcTerminate_nid_no_patch(code);
|
||||
}
|
||||
|
||||
[[noreturn]] void LibcTerminate_nid_no_patch(int code) {
|
||||
#ifdef _WIN32
|
||||
TerminateProcess(GetCurrentProcess(), static_cast<UINT>(code));
|
||||
#endif
|
||||
std::_Exit(code);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ void APS5_VABI exit_nid_postfix(int code) {
|
|||
}
|
||||
|
||||
[[noreturn]] void APS5_VABI _exit_nid_postfix(int status) {
|
||||
std::_Exit(status);
|
||||
LibcTerminate_nid_no_patch(status);
|
||||
}
|
||||
|
||||
int APS5_VABI system_nid_postfix(const char* command) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@
|
|||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
extern "C" int APS5_VABI sceSystemServiceLoadExec(const char*, const char* const*);
|
||||
extern "C" void APS5_VABI _Exit_nid_postfix(int);
|
||||
extern "C" void APS5_VABI catchReturnFromMain_nid_postfix(int);
|
||||
|
|
@ -27,11 +30,18 @@ void APS5_VABI QuickFirst() {
|
|||
}
|
||||
void Require(bool value) { if (!value) std::abort(); }
|
||||
void UnexpectedCleanup() { std::_Exit(3); }
|
||||
#ifdef _WIN32
|
||||
void WINAPI UnexpectedDetach(PVOID) { TerminateProcess(GetCurrentProcess(), 4); }
|
||||
#endif
|
||||
}
|
||||
int main(int argc, char** argv) {
|
||||
if (argc > 1 && std::strcmp(argv[1], "--immediate") == 0) {
|
||||
LibcRegisterShutdown_nid_postfix(UnexpectedCleanup);
|
||||
Require(std::atexit(UnexpectedCleanup) == 0);
|
||||
#ifdef _WIN32
|
||||
auto slot = FlsAlloc(UnexpectedDetach);
|
||||
Require(slot != FLS_OUT_OF_INDEXES && FlsSetValue(slot, &slot));
|
||||
#endif
|
||||
_Exit_nid_postfix(0);
|
||||
return 2;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue