Move the fatal error logging out of win32 and use it on Linux and macOS

This commit is contained in:
Magnus Norddahl 2025-04-20 23:19:29 +02:00
commit 213305cc2d
13 changed files with 103 additions and 127 deletions

View file

@ -65,6 +65,7 @@
#include "g_input.h"
#include "c_commandbuffer.h"
#include "vm.h"
#include "common/widgets/errorwindow.h"
#define LEFTMARGIN 8
#define RIGHTMARGIN 8
@ -411,6 +412,76 @@ void WriteLineToLog(FILE *LogFile, const char *outline)
bool DisableLogging;
extern bool gameisdead;
bool IsZWidgetAvailable();
TArray<FString> bufferedConsoleStuff;
bool restartrequest = false;
void GetLog(std::function<bool(const void* data, uint32_t size, uint32_t& written)> writeData)
{
for (const FString& line : bufferedConsoleStuff)
{
size_t pos = 0;
size_t len = line.Len();
while (pos < len)
{
uint32_t size = (uint32_t)std::min(len - pos, 0x0fffffffULL);
uint32_t written = 0;
if (!writeData(&line[pos], size, written))
return;
pos += written;
}
}
}
void DeleteStartupScreen();
void S_StopMusic(bool);
void I_CloseMainWindow();
void ShowFatalError(const char* text)
{
DeleteStartupScreen();
S_StopMusic(true);
I_CloseMainWindow();
if (batchrun || RunningAsTool)
{
Printf(TEXTCOLOR_ORANGE "%s\n", text);
return;
}
if (CVMAbortException::stacktrace.IsNotEmpty())
{
Printf("%s", CVMAbortException::stacktrace.GetChars());
}
if (!batchrun && !RunningAsTool)
{
size_t totalsize = 0;
for (const FString& line : bufferedConsoleStuff)
totalsize += line.Len();
std::string alltext;
alltext.reserve(totalsize);
for (const FString& line : bufferedConsoleStuff)
alltext.append(line.GetChars(), line.Len());
if (IsZWidgetAvailable())
{
restartrequest = ErrorWindow::ExecModal(text, alltext);
}
else // We are aborting before we even got to load zdoom.pk3
{
I_ShowFatalError(text);
restartrequest = false;
}
}
else
{
Printf(TEXTCOLOR_ORANGE "%s\n", text);
}
}
int PrintString (int iprintlevel, const char *outline)
{
if ((!RunningAsTool && gameisdead) || DisableLogging)
@ -430,6 +501,7 @@ int PrintString (int iprintlevel, const char *outline)
if (printlevel != PRINT_LOG)
{
bufferedConsoleStuff.Push(outline);
I_PrintStr(outline);
conbuffer->AddText(printlevel, outline);

View file

@ -66,9 +66,11 @@ void C_Ticker (void);
void AddToConsole (int printlevel, const char *string);
int PrintString (int printlevel, const char *string);
int PrintStringHigh (const char *string);
int VPrintf (int printlevel, const char *format, va_list parms) GCCFORMAT(2);
void GetLog(std::function<bool(const void* data, uint32_t size, uint32_t& written)> writeFile);
void ShowFatalError(const char* msg);
void C_DrawConsole ();
void C_ToggleConsole (void);
void C_FullConsole (void);

View file

@ -122,6 +122,11 @@ void I_ShowFatalError(const char *message)
Mac_I_FatalError(message);
}
void I_CloseMainWindow()
{
I_SetMainWindowVisible(false);
}
int I_PickIWad(WadStuff* const wads, const int numwads, const bool showwin, const int defaultiwad, int&, FString&)
{

View file

@ -45,7 +45,6 @@
IVideo *Video;
void I_RestartRenderer();
void I_ShutdownGraphics ()

View file

@ -67,10 +67,6 @@
#include "printf.h"
#include "launcherwindow.h"
#include "common/widgets/errorwindow.h"
bool IsZWidgetAvailable();
#ifndef NO_GTK
bool I_GtkAvailable ();
void I_ShowFatalError_Gtk(const char* errortext);
@ -141,25 +137,22 @@ void Unix_I_FatalError(const char* errortext)
}
}
}
void I_CloseMainWindow()
{
// To do: close the window but do NOT call SDL_QuitSubSystem as ZWidget may also be using it
}
#endif
void I_ShowFatalError(const char *message)
{
if (IsZWidgetAvailable())
{
// To do: move the console buffer stuff out of the win32 specific stuff so we can use it here...
ErrorWindow::ExecModal(message, message);
}
else
{
#ifdef __APPLE__
Mac_I_FatalError(message);
Mac_I_FatalError(message);
#else
Unix_I_FatalError(message);
Unix_I_FatalError(message);
#endif
}
}
bool PerfAvailable;

View file

@ -52,7 +52,6 @@
IVideo *Video;
void I_RestartRenderer();
int currentcanvas = -1;
bool changerenderer;

View file

@ -27,6 +27,7 @@
#include <thread>
#include "i_mainwindow.h"
#include "version.h"
#include "c_console.h"
#ifdef _MSC_VER
#include <dbghelp.h>
@ -227,7 +228,7 @@ void CrashReporter::create_dump(DumpParams* dump_params, bool launch_uploader)
written = tmp;
return result == TRUE;
};
mainwindow.GetLog(writeFile);
GetLog(writeFile);
CloseHandle(file);
if (launch_uploader && !uploader_exe.empty())

View file

@ -196,6 +196,8 @@ void InitExePath()
//==========================================================================
extern bool restartrequest;
int DoMain (HINSTANCE hInstance)
{
LONG WinWidth, WinHeight;
@ -301,7 +303,7 @@ int DoMain (HINSTANCE hInstance)
int ret = GameMain ();
if (mainwindow.CheckForRestart())
if (restartrequest)
{
HMODULE hModule = GetModuleHandleW(nullptr);
WCHAR path[MAX_PATH];
@ -325,10 +327,6 @@ int DoMain (HINSTANCE hInstance)
SetConsoleMode(stdinput, 0);
ReadConsole(stdinput, &bytes, 1, &bytes, nullptr);
}
else if (StdOut == nullptr)
{
mainwindow.ShowErrorPane(nullptr);
}
}
}
return ret;
@ -336,24 +334,15 @@ int DoMain (HINSTANCE hInstance)
void I_ShowFatalError(const char *msg)
{
I_ShutdownGraphics ();
if (!RunningAsTool)
mainwindow.RestoreConView();
S_StopMusic(true);
MessageBoxA(0, msg, "Fatal Error", MB_OK | MB_ICONERROR);
}
if (CVMAbortException::stacktrace.IsNotEmpty())
{
Printf("%s", CVMAbortException::stacktrace.GetChars());
}
if (!batchrun && !RunningAsTool)
{
mainwindow.ShowErrorPane(msg);
}
else
{
Printf(TEXTCOLOR_ORANGE "%s\n", msg);
}
void I_CloseMainWindow()
{
I_ShutdownGraphics();
I_ShutdownInput();
if (mainwindow.GetHandle())
ShowWindow(mainwindow.GetHandle(), SW_HIDE);
}
void I_SetWindowTitle(const char* caption)

View file

@ -20,8 +20,6 @@
#pragma comment(lib, "dwmapi.lib")
bool IsZWidgetAvailable();
MainWindow mainwindow;
void MainWindow::Create(const FString& caption, int x, int y, int width, int height)
@ -88,81 +86,12 @@ void MainWindow::ShowGameView()
}
}
// Returns the main window to its startup state.
void MainWindow::RestoreConView()
{
I_ShutdownInput(); // Make sure the mouse pointer is available.
ShowWindow(Window, SW_HIDE);
// Make sure the progress bar isn't visible.
DeleteStartupScreen();
}
// Shows an error message, preferably in the main window, but it can use a normal message box too.
void MainWindow::ShowErrorPane(const char* text)
{
if (StartWindow) // Ensure that the network pane is hidden.
{
I_NetDone();
}
// PrintStr(text);
size_t totalsize = 0;
for (const FString& line : bufferedConsoleStuff)
totalsize += line.Len();
std::string alltext;
alltext.reserve(totalsize);
for (const FString& line : bufferedConsoleStuff)
alltext.append(line.GetChars(), line.Len());
if (IsZWidgetAvailable())
{
restartrequest = ErrorWindow::ExecModal(text, alltext);
}
else // We are aborting before we even got to load zdoom.pk3
{
MessageBoxA(0, text, "Fatal Error", MB_OK | MB_ICONERROR);
restartrequest = false;
}
}
bool MainWindow::CheckForRestart()
{
bool result = restartrequest;
restartrequest = false;
return result;
}
// The main window's WndProc during startup. During gameplay, the WndProc in i_input.cpp is used instead.
LRESULT MainWindow::LConProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, msg, wParam, lParam);
}
void MainWindow::PrintStr(const char* cp)
{
bufferedConsoleStuff.Push(cp);
}
void MainWindow::GetLog(std::function<bool(const void* data, uint32_t size, uint32_t& written)> writeData)
{
for (const FString& line : bufferedConsoleStuff)
{
size_t pos = 0;
size_t len = line.Len();
while (pos < len)
{
uint32_t size = (uint32_t)std::min(len - pos, 0x0fffffffULL);
uint32_t written = 0;
if (!writeData(&line[pos], size, written))
return;
pos += written;
}
}
}
// each platform has its own specific version of this function.
void MainWindow::SetWindowTitle(const char* caption)
{

View file

@ -17,13 +17,6 @@ public:
void Create(const FString& title, int x, int y, int width, int height);
void ShowGameView();
void RestoreConView();
void ShowErrorPane(const char* text);
bool CheckForRestart();
void PrintStr(const char* cp);
void GetLog(std::function<bool(const void* data, uint32_t size, uint32_t& written)> writeFile);
void SetWindowTitle(const char* caption);
@ -33,8 +26,6 @@ private:
static LRESULT CALLBACK LConProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
HWND Window = 0;
bool restartrequest = false;
TArray<FString> bufferedConsoleStuff;
};
extern MainWindow mainwindow;

View file

@ -335,7 +335,6 @@ static void PrintToStdOut(const char *cpt, HANDLE StdOut)
void I_PrintStr(const char *cp)
{
mainwindow.PrintStr(cp);
PrintToStdOut(cp, StdOut);
}

View file

@ -23,10 +23,6 @@ void I_ShutdownGraphics();
extern IVideo *Video;
void I_PolyPresentInit();
uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch);
void I_PolyPresentUnlock(int x, int y, int w, int h);
void I_PolyPresentDeinit();
#endif // __I_VIDEO_H__

View file

@ -3936,9 +3936,10 @@ int GameMain()
}
catch (const std::exception &error)
{
I_ShowFatalError(error.what());
ShowFatalError(error.what());
ret = -1;
}
// Unless something really bad happened, the game should only exit through this single point in the code.
// No more 'exit', please.
D_Cleanup();