mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
Write a fatal error's frame-time summary after RivaTuner's restore and the rumble stop, not before them.
The review of the fatal summary change found that dispatch.c fatal_end called perf_summary_flush_try (ft_stop waits up to 50 ms, then the summary and the stutter map are formatted) before rtss_limit_restore and rt_rumble_stop_bounded. The lane's order for the failed ends, and A-6's for the orderly ones (gfx_present.c rt_exit_steps), puts what a kill of the process must not lose first: RTSS's profile and the controller's rumble. perf_summary_flush_try now runs after the restore and the bounded rumble stop, just before the stdio flushes and plat_terminate. The summary's lines still reach the log: rt_log_sync ran at the start of fatal_end, so every later line is written as it is made. Not reproduced before the change (an order of steps). tests/fatal_exit_check.py checks statically that fatal_end calls perf_summary_flush_try after rt_rumble_stop_bounded; the check fails on the code before this change and passes after it, and the program's cases (fatal, fatal_rumble, crash_crash, fatal_crash, crash_fatal) pass. The compile check of dispatch.c passes with no -Wall warnings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -116,12 +116,14 @@ static void fatal_end(int code, const char *fmt, va_list ap) {
|
||||
rt_fatal_notes();
|
||||
kern_free_cores_note();
|
||||
fs_save_crash_wait(); // a save the game already reported as done finishes first (bounded)
|
||||
perf_summary_flush_try(); // "frametime: at a fatal error" and the stutter map: the session's last period
|
||||
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();
|
||||
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
|
||||
perf_summary_flush_try();
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
// Not _Exit: in the C runtime it is ExitProcess, which stops the other threads wherever they are and then runs every
|
||||
|
||||
@@ -94,6 +94,12 @@ def static_checks():
|
||||
print(f'static: {name} stops HD rumble through rt_rumble_stop_bounded after the RTSS restore: '
|
||||
f'{"ok" if ok else "FAIL"}', flush=True)
|
||||
bad += not ok
|
||||
# the fatal error's frame-time summary comes after the RTSS restore and the rumble stop, as in the orderly end
|
||||
s, p = fatal.find('rt_rumble_stop_bounded('), fatal.find('perf_summary_flush_try(')
|
||||
ok = 0 <= s < p
|
||||
print(f'static: dispatch.c fatal_end writes the frame-time summary after the RTSS restore and the rumble stop: '
|
||||
f'{"ok" if ok else "FAIL"}', flush=True)
|
||||
bad += not ok
|
||||
return bad
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user