mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
Skip RivaTuner's restore at a fatal error on the RTSS thread too, not only at a crash there.
The review of the RTSS thread change found that only main.c crash_handler skipped rtss_limit_restore on the "rtss" thread. An rt_fatal on that thread while it holds rtss_limit.c's lock still called the restore from dispatch.c fatal_end, whose trylocks then spent a second for nothing before the end went on. A-14 names fatal_end. fatal_end now reads plat_thread_name and calls rtss_limit_restore only when the thread is not "rtss", as crash_handler does. Not reproduced in the game before the change. tests/fatal_exit_check.c's stand-in restore now says it ran, and a new fatal_rtss mode calls rt_fatal on a thread spawned with the name "rtss": on the code before this change the restore ran there (the check fails), now it does not, and the process still ends with 70 after the rumble stop. The other cases check that the restore runs from any other thread. fatal_exit_check and the compile check of dispatch.c pass, with no -Wall warnings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -118,8 +118,11 @@ static void fatal_end(int code, const char *fmt, va_list ap) {
|
||||
fs_save_crash_wait(); // a save the game already reported as done finishes first (bounded)
|
||||
prof_sampler_write(); // NX2NAVI_PROFILE: what was sampled until now, else a crash loses the whole profile
|
||||
// RivaTuner Statistics Server's profile as it was: left with the game's limit in it, the next run would take that
|
||||
// limit for the player's own (rtss_limit.c; it gives up after a second if the failing thread holds its lock)
|
||||
rtss_limit_restore();
|
||||
// limit for the player's own (rtss_limit.c; it gives up after a second if the failing thread holds its lock). Not
|
||||
// from RTSS's own thread, which may hold that lock: the restore would spend its second for nothing (as in main.c
|
||||
// crash_handler).
|
||||
const char *thread = plat_thread_name();
|
||||
if (!thread || strcmp(thread, "rtss")) rtss_limit_restore();
|
||||
rt_rumble_stop_bounded(); // a controller on HD rumble: nothing renews or stops its vibration after the end
|
||||
// "frametime: at a fatal error" and the stutter map, the session's last period: after what a kill of the process
|
||||
// must not lose, as in the orderly end (gfx_present.c rt_exit_steps); ft_stop waits up to 50 ms
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
// fatal_exit_check fatal_crash a fault on another thread while rt_fatal reports: its FATAL line alone, exit code 70
|
||||
// fatal_exit_check crash_fatal rt_fatal on another thread while a crash is reported: the whole report, exit code 71
|
||||
// fatal_exit_check fatal_rumble rt_fatal while the HD rumble stop hangs (SDL's lock held): exit code 70 all the same
|
||||
// fatal_exit_check fatal_rtss rt_fatal on RTSS's thread ("rtss"): exit code 70, no RTSS restore from there
|
||||
//
|
||||
// The crash handler here is a stand-in for main.c crash_handler with its first line (the static check in
|
||||
// tests/fatal_exit_check.py holds main.c to it): it writes three report lines 100 ms apart and ends with plat_exit(71).
|
||||
@@ -58,7 +59,7 @@ void rt_log(const char *fmt, ...) {
|
||||
}
|
||||
void kern_free_cores_note(void) {}
|
||||
void prof_sampler_write(void) {}
|
||||
void rtss_limit_restore(void) {}
|
||||
void rtss_limit_restore(void) { say("rtss: restored\n"); }
|
||||
void kern_checkpoint(void) {}
|
||||
|
||||
// perf.c's summary at a fatal error, which dispatch.c calls through a weak symbol
|
||||
@@ -94,6 +95,10 @@ static DWORD WINAPI fatal_thread(void *arg) {
|
||||
Sleep((DWORD)(uintptr_t)arg);
|
||||
rt_fatal("the test's fatal error %d", 2);
|
||||
}
|
||||
static void rtss_thread(void *arg) { // rtss_limit.c's worker, named as plat_thread_spawn names it there
|
||||
(void)arg;
|
||||
rt_fatal("the test's fatal error %d", 3);
|
||||
}
|
||||
static void slow_note(void) { // a fatal note that takes a while, as the card's and the memory settings' may
|
||||
say("fatal note: start\n");
|
||||
Sleep(300);
|
||||
@@ -130,6 +135,11 @@ int main(int argc, char **argv) {
|
||||
fault(0);
|
||||
return 3;
|
||||
}
|
||||
printf("usage: fatal_exit_check fatal|crash_crash|fatal_crash|crash_fatal|fatal_rumble\n");
|
||||
if (!strcmp(mode, "fatal_rtss")) {
|
||||
plat_thread_spawn(rtss_thread, NULL, "rtss", 0);
|
||||
Sleep(10000);
|
||||
return 3;
|
||||
}
|
||||
printf("usage: fatal_exit_check fatal|crash_crash|fatal_crash|crash_fatal|fatal_rumble|fatal_rtss\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ checks statically that no runtime file outside the platform layer ends the proce
|
||||
error's end and the lost device's (runtime/vk_device.c lost_wait_exit) end with plat_terminate. No game files, no GPU.
|
||||
|
||||
A fatal error stops HD rumble on a thread of its own and waits for it 300 ms at most (runtime/dispatch.c
|
||||
rt_rumble_stop_bounded), so a stop that hangs on SDL's lock does not hold the end.
|
||||
rt_rumble_stop_bounded), so a stop that hangs on SDL's lock does not hold the end. A fatal error on RTSS's own thread
|
||||
("rtss") skips RivaTuner's restore, whose lock that thread may hold.
|
||||
|
||||
Two failures at once end once: two threads that fault, a fault while a fatal error is reported and a fatal error
|
||||
while a crash is: the first report is written whole, the process ends with its code, and the second adds no line
|
||||
@@ -105,7 +106,10 @@ def static_checks():
|
||||
|
||||
CASES = [
|
||||
# mode, exit code, lines that must be there, lines that must not
|
||||
('fatal', 70, ['FATAL: the test\'s fatal error 1', 'frametime: at a fatal error', 'rumble: stopped'], ['detach:']),
|
||||
('fatal', 70, ['FATAL: the test\'s fatal error 1', 'frametime: at a fatal error', 'rumble: stopped', 'rtss: restored'],
|
||||
['detach:']),
|
||||
# rt_fatal on RTSS's own thread, which may hold the lock the restore tries: no restore from there
|
||||
('fatal_rtss', 70, ['FATAL: the test\'s fatal error 3', 'rumble: stopped'], ['rtss: restored', 'detach:']),
|
||||
# the rumble stop hangs (SDL's lock held by a thread that crashed): the end goes on after 300 ms
|
||||
('fatal_rumble', 70, ['FATAL: the test\'s fatal error 1'], ['rumble: stopped', 'detach:']),
|
||||
# two faults at once: the first report whole, the second thread waits (dispatch.c rt_ending_enter)
|
||||
|
||||
Reference in New Issue
Block a user