From f5822c16afcca5fab4b3504185294a1608c18a2c Mon Sep 17 00:00:00 2001 From: Coxxs <58-coxxs@users.noreply.git.ryujinx.app> Date: Mon, 13 Oct 2025 17:40:15 -0500 Subject: [PATCH] Flush the error log before exit Currently, some logs can be missing when a fatal error occurs (especially GuestBrokeExecutionException). This MR attempts to flush logs to console and file before process exit. --- src/Ryujinx.Common/Logging/Logger.cs | 11 +++++ .../Logging/Targets/AsyncLogTargetWrapper.cs | 41 ++++++++++++++++++- .../HOS/Kernel/Process/KProcess.cs | 4 ++ .../HOS/Kernel/SupervisorCall/Syscall.cs | 3 ++ src/Ryujinx/Program.cs | 1 + 5 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/Ryujinx.Common/Logging/Logger.cs b/src/Ryujinx.Common/Logging/Logger.cs index 817ed2115..bcc2298b6 100644 --- a/src/Ryujinx.Common/Logging/Logger.cs +++ b/src/Ryujinx.Common/Logging/Logger.cs @@ -187,6 +187,17 @@ namespace Ryujinx.Common.Logging } } + public static void Flush() + { + foreach (ILogTarget target in _logTargets) + { + if (target is AsyncLogTargetWrapper asyncTarget) + { + asyncTarget.Flush(); + } + } + } + public static void Shutdown() { Updated = null; diff --git a/src/Ryujinx.Common/Logging/Targets/AsyncLogTargetWrapper.cs b/src/Ryujinx.Common/Logging/Targets/AsyncLogTargetWrapper.cs index 1fcfea4da..34f52d6ab 100644 --- a/src/Ryujinx.Common/Logging/Targets/AsyncLogTargetWrapper.cs +++ b/src/Ryujinx.Common/Logging/Targets/AsyncLogTargetWrapper.cs @@ -27,6 +27,17 @@ namespace Ryujinx.Common.Logging.Targets private readonly int _overflowTimeout; + private sealed class FlushEventArgs : LogEventArgs + { + public readonly ManualResetEventSlim SignalEvent; + + public FlushEventArgs(ManualResetEventSlim signalEvent) + : base(LogLevel.Notice, TimeSpan.Zero, string.Empty, string.Empty) + { + SignalEvent = signalEvent; + } + } + string ILogTarget.Name => _target.Name; public AsyncLogTargetWrapper(ILogTarget target, int queueLimit = -1, AsyncLogTargetOverflowAction overflowAction = AsyncLogTargetOverflowAction.Block) @@ -41,7 +52,15 @@ namespace Ryujinx.Common.Logging.Targets { try { - _target.Log(this, _messageQueue.Take()); + LogEventArgs item = _messageQueue.Take(); + + if (item is FlushEventArgs flush) + { + flush.SignalEvent.Set(); + continue; + } + + _target.Log(this, item); } catch (InvalidOperationException) { @@ -68,6 +87,26 @@ namespace Ryujinx.Common.Logging.Targets } } + public void Flush() + { + if (_messageQueue.Count == 0 || _messageQueue.IsAddingCompleted) + { + return; + } + + using var signal = new ManualResetEventSlim(false); + try + { + _messageQueue.Add(new FlushEventArgs(signal)); + } + catch (InvalidOperationException) + { + return; + } + + signal.Wait(); + } + public void Dispose() { GC.SuppressFinalize(this); diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index ba80522e7..efff992ef 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -1084,6 +1084,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process Logger.Error?.Print(LogClass.Cpu, $"Invalid memory access at virtual address 0x{va:X16}."); + Logger.Flush(); + return false; } @@ -1092,6 +1094,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process KernelStatic.GetCurrentThread().PrintGuestStackTrace(); KernelStatic.GetCurrentThread()?.PrintGuestRegisterPrintout(); + Logger.Flush(); + throw new UndefinedInstructionException(address, opCode); } diff --git a/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs index d27e4f3d2..f9cd67b35 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs @@ -1885,6 +1885,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return; } + Logger.Error?.Print(LogClass.KernelSvc, "The guest program broke execution!"); + Logger.Flush(); + // TODO: Debug events. currentThread.Owner.TerminateCurrentProcess(); diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 623a3b767..5d231d54f 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -272,6 +272,7 @@ namespace Ryujinx.Ava if (isTerminating) { + Logger.Flush(); Exit(); } }