mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
Create a class for deferred error logging (#390)
## Link to GitHub Issue, if one exists #388 ## Description of change Instead of setting flags in `signal` and logging when we crash, create a class for logging deferred semi-fatal messages, and dump them to the log immediately before crashing or shutting down. ## Testing Tested each failure case by injection.
This commit is contained in:
@@ -611,6 +611,7 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
util/tapeled.cpp
|
util/tapeled.cpp
|
||||||
util/execexe.cpp
|
util/execexe.cpp
|
||||||
util/dependencies.cpp
|
util/dependencies.cpp
|
||||||
|
util/deferlog.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOURCE_FILES})
|
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOURCE_FILES})
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "external/robin_hood.h"
|
#include "external/robin_hood.h"
|
||||||
#include "launcher/logger.h"
|
#include "launcher/logger.h"
|
||||||
#include "launcher/signal.h"
|
#include "launcher/signal.h"
|
||||||
|
#include "util/deferlog.h"
|
||||||
#include "util/detour.h"
|
#include "util/detour.h"
|
||||||
#include "util/fileutils.h"
|
#include "util/fileutils.h"
|
||||||
#include "util/libutils.h"
|
#include "util/libutils.h"
|
||||||
@@ -1739,8 +1740,12 @@ namespace avs {
|
|||||||
|
|
||||||
static void avs_dir_err(const std::filesystem::path &src_path)
|
static void avs_dir_err(const std::filesystem::path &src_path)
|
||||||
{
|
{
|
||||||
launcher::signal::AVS_DIR_CREATION_FAILURE = TRUE;
|
deferredlogs::defer_error_messages({
|
||||||
launcher::signal::AVS_SRC_PATH = src_path.string();
|
"AVS filesystem initialization failure was previously detected during boot!",
|
||||||
|
fmt::format(" ERROR: directory could not be created: {}", src_path.string().c_str()),
|
||||||
|
fmt::format(" this crash may have been caused by bad <mounttable> contents in {}", avs::core::CFG_PATH.c_str()),
|
||||||
|
" fix the XML file and try again"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_avs_dir(
|
static void create_avs_dir(
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "misc/wintouchemu.h"
|
#include "misc/wintouchemu.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "util/detour.h"
|
#include "util/detour.h"
|
||||||
|
#include "util/deferlog.h"
|
||||||
#include "util/fileutils.h"
|
#include "util/fileutils.h"
|
||||||
#include "util/libutils.h"
|
#include "util/libutils.h"
|
||||||
#include "util/memutils.h"
|
#include "util/memutils.h"
|
||||||
@@ -235,7 +236,7 @@ namespace games::iidx {
|
|||||||
out.clear();
|
out.clear();
|
||||||
return true;
|
return true;
|
||||||
} else if (data.find("SuperstepSound: Audio device is not available") != std::string::npos) {
|
} else if (data.find("SuperstepSound: Audio device is not available") != std::string::npos) {
|
||||||
launcher::signal::SUPERSTEP_SOUND_ERROR = TRUE;
|
deferredlogs::defer_error_messages(deferredlogs::SUPERSTEP_SOUND_ERROR_MESSAGE);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "hooks/sleephook.h"
|
#include "hooks/sleephook.h"
|
||||||
#include "hooks/winuser.h"
|
#include "hooks/winuser.h"
|
||||||
#include "touch/touch.h"
|
#include "touch/touch.h"
|
||||||
|
#include "util/deferlog.h"
|
||||||
#include "util/detour.h"
|
#include "util/detour.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "util/sigscan.h"
|
#include "util/sigscan.h"
|
||||||
@@ -211,7 +212,7 @@ namespace games::sdvx {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (data.find("SuperstepSound: Audio device is not available") != std::string::npos) {
|
if (data.find("SuperstepSound: Audio device is not available") != std::string::npos) {
|
||||||
launcher::signal::SUPERSTEP_SOUND_ERROR = TRUE;
|
deferredlogs::defer_error_messages(deferredlogs::SUPERSTEP_SOUND_ERROR_MESSAGE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "misc/wintouchemu.h"
|
#include "misc/wintouchemu.h"
|
||||||
#include "overlay/overlay.h"
|
#include "overlay/overlay.h"
|
||||||
#include "util/detour.h"
|
#include "util/detour.h"
|
||||||
|
#include "util/deferlog.h"
|
||||||
#include "util/flags_helper.h"
|
#include "util/flags_helper.h"
|
||||||
#include "util/libutils.h"
|
#include "util/libutils.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
@@ -204,6 +205,18 @@ static std::string presentation_interval2s(UINT presentation_interval) {
|
|||||||
|
|
||||||
static void update_backbuffer_dimensions(D3DPRESENT_PARAMETERS *params);
|
static void update_backbuffer_dimensions(D3DPRESENT_PARAMETERS *params);
|
||||||
|
|
||||||
|
static void log_create_device_failure(HRESULT hresult) {
|
||||||
|
deferredlogs::defer_error_messages({
|
||||||
|
fmt::format("D3D9 CreateDevice/CreateDeviceEx failed with {:#x}!", (UINT)hresult),
|
||||||
|
" this is a common graphics / monitor issue",
|
||||||
|
" double check any graphics options you configured in spicecfg",
|
||||||
|
" double check that your monitor supports the resolution + refresh rate that the game needs",
|
||||||
|
" enable GPU-side resolution scaling in your GPU options as needed",
|
||||||
|
" if you have three or more monitors, try unplugging them down to one or two, or enable -graphics-force-single-adapter option",
|
||||||
|
" failing all that, see if enabling windowed mode helps"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static bool is_dx9_on_12_enabled() {
|
static bool is_dx9_on_12_enabled() {
|
||||||
switch (GRAPHICS_9_ON_12_STATE) {
|
switch (GRAPHICS_9_ON_12_STATE) {
|
||||||
case DX9ON12_FORCE_OFF:
|
case DX9ON12_FORCE_OFF:
|
||||||
@@ -776,8 +789,7 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::CreateDevice(
|
|||||||
|
|
||||||
// log error
|
// log error
|
||||||
log_info("graphics::d3d9", "IDirect3D9::CreateDevice failed, hr={}", FMT_HRESULT(ret));
|
log_info("graphics::d3d9", "IDirect3D9::CreateDevice failed, hr={}", FMT_HRESULT(ret));
|
||||||
launcher::signal::D3D9_CREATE_DEVICE_FAILED = true;
|
log_create_device_failure(ret);
|
||||||
launcher::signal::D3D9_CREATE_DEVICE_FAILED_HRESULT = ret;
|
|
||||||
} else if (!D3D9_DEVICE_HOOK_DISABLE) {
|
} else if (!D3D9_DEVICE_HOOK_DISABLE) {
|
||||||
graphics_hook_window(hFocusWindow, pPresentationParameters);
|
graphics_hook_window(hFocusWindow, pPresentationParameters);
|
||||||
|
|
||||||
@@ -997,8 +1009,7 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::CreateDeviceEx(
|
|||||||
|
|
||||||
// log error
|
// log error
|
||||||
log_warning("graphics::d3d9", "CreateDeviceEx failed, hr={}", FMT_HRESULT(result));
|
log_warning("graphics::d3d9", "CreateDeviceEx failed, hr={}", FMT_HRESULT(result));
|
||||||
launcher::signal::D3D9_CREATE_DEVICE_FAILED = true;
|
log_create_device_failure(result);
|
||||||
launcher::signal::D3D9_CREATE_DEVICE_FAILED_HRESULT = result;
|
|
||||||
|
|
||||||
} else if (!D3D9_DEVICE_HOOK_DISABLE) {
|
} else if (!D3D9_DEVICE_HOOK_DISABLE) {
|
||||||
graphics_hook_window(hFocusWindow, pPresentationParameters);
|
graphics_hook_window(hFocusWindow, pPresentationParameters);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "easrv/easrv.h"
|
#include "easrv/easrv.h"
|
||||||
#include "rawinput/rawinput.h"
|
#include "rawinput/rawinput.h"
|
||||||
#include "hooks/audio/audio.h"
|
#include "hooks/audio/audio.h"
|
||||||
|
#include "util/deferlog.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
|
|
||||||
#include "launcher.h"
|
#include "launcher.h"
|
||||||
@@ -21,6 +22,9 @@ namespace launcher {
|
|||||||
// therefore, subsystems need to be guarded against multiple unload attempts
|
// therefore, subsystems need to be guarded against multiple unload attempts
|
||||||
log_info("launcher", "stopping subsystems");
|
log_info("launcher", "stopping subsystems");
|
||||||
|
|
||||||
|
// before shutting down logger, dump any deferred log messages
|
||||||
|
deferredlogs::dump_to_logger();
|
||||||
|
|
||||||
// flush/stop logger
|
// flush/stop logger
|
||||||
logger::stop();
|
logger::stop();
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,11 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <dbghelp.h>
|
#include <dbghelp.h>
|
||||||
|
|
||||||
#include "avs/core.h"
|
|
||||||
#include "avs/game.h"
|
|
||||||
#include "acio/acio.h"
|
#include "acio/acio.h"
|
||||||
#include "external/stackwalker/stackwalker.h"
|
#include "external/stackwalker/stackwalker.h"
|
||||||
#include "hooks/libraryhook.h"
|
#include "hooks/libraryhook.h"
|
||||||
#include "launcher/shutdown.h"
|
#include "launcher/shutdown.h"
|
||||||
|
#include "util/deferlog.h"
|
||||||
#include "util/detour.h"
|
#include "util/detour.h"
|
||||||
#include "util/libutils.h"
|
#include "util/libutils.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
@@ -30,13 +29,6 @@ namespace launcher::signal {
|
|||||||
// settings
|
// settings
|
||||||
bool DISABLE = false;
|
bool DISABLE = false;
|
||||||
bool USE_VEH_WORKAROUND = false;
|
bool USE_VEH_WORKAROUND = false;
|
||||||
|
|
||||||
// states
|
|
||||||
bool SUPERSTEP_SOUND_ERROR = false;
|
|
||||||
bool AVS_DIR_CREATION_FAILURE = false;
|
|
||||||
std::string AVS_SRC_PATH;
|
|
||||||
bool D3D9_CREATE_DEVICE_FAILED = false;
|
|
||||||
uint32_t D3D9_CREATE_DEVICE_FAILED_HRESULT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define V(variant) case variant: return #variant
|
#define V(variant) case variant: return #variant
|
||||||
@@ -124,54 +116,11 @@ static LONG WINAPI TopLevelExceptionFilter(struct _EXCEPTION_POINTERS *Exception
|
|||||||
|
|
||||||
// check ACIO init failures
|
// check ACIO init failures
|
||||||
if (acio::IO_INIT_IN_PROGRESS) {
|
if (acio::IO_INIT_IN_PROGRESS) {
|
||||||
log_warning(
|
deferredlogs::defer_error_messages({
|
||||||
"signal",
|
"exception raised during ACIO init, this usually happens when a third party application interferes with hooks",
|
||||||
"exception raised during ACIO init, this usually happens when a third party application interferes with hooks");
|
" please check for the following, disable them, and try launching the game again:",
|
||||||
log_warning(
|
" RivaTuner Statistics Server (RTSS), MSI Afterburner, kernel mode anti-cheat"
|
||||||
"signal",
|
});
|
||||||
" please check for the following, disable them, and try launching the game again:");
|
|
||||||
log_warning(
|
|
||||||
"signal",
|
|
||||||
" RivaTuner Statistics Server (RTSS), MSI Afterburner, kernel mode anti-cheat");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (launcher::signal::SUPERSTEP_SOUND_ERROR) {
|
|
||||||
log_warning("signal", "audio initialization error was previously detected during boot!");
|
|
||||||
log_warning("signal", " (W:SuperstepSound: Audio device is not available!!!)");
|
|
||||||
log_warning("signal", " this crash is most likely related to audio init failure");
|
|
||||||
log_warning("signal", " see if the default audio device changed, fix your audio configuration (e.g., sample rate)");
|
|
||||||
log_warning("signal", " double check your spice audio options/patches, and try again");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (launcher::signal::AVS_DIR_CREATION_FAILURE) {
|
|
||||||
log_warning("signal",
|
|
||||||
"AVS filesystem initialization failure was previously detected during boot!");
|
|
||||||
log_warning("signal",
|
|
||||||
" ERROR: directory could not be created: {}",
|
|
||||||
launcher::signal::AVS_SRC_PATH.c_str());
|
|
||||||
log_warning("signal",
|
|
||||||
" this crash may have been caused by bad <mounttable> contents in {}",
|
|
||||||
avs::core::CFG_PATH.c_str());
|
|
||||||
log_warning("signal", " fix the XML file and try again");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (launcher::signal::D3D9_CREATE_DEVICE_FAILED) {
|
|
||||||
log_warning("signal",
|
|
||||||
"D3D9 CreateDevice/CreateDeviceEx failed with {:#x}!",
|
|
||||||
launcher::signal::D3D9_CREATE_DEVICE_FAILED_HRESULT);
|
|
||||||
|
|
||||||
log_warning("signal",
|
|
||||||
" this is a common graphics / monitor issue");
|
|
||||||
log_warning("signal",
|
|
||||||
" double check any graphics options you configured in spicecfg");
|
|
||||||
log_warning("signal",
|
|
||||||
" double check that your monitor supports the resolution + refresh rate that the game needs");
|
|
||||||
log_warning("signal",
|
|
||||||
" enable GPU-side resolution scaling in your GPU options as needed");
|
|
||||||
log_warning("signal",
|
|
||||||
" if you have three or more monitors, try unplugging them down to one or two, or enable -graphics-force-single-adapter option");
|
|
||||||
log_warning("signal",
|
|
||||||
" failing all that, see if enabling windowed mode helps");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk the exception chain
|
// walk the exception chain
|
||||||
@@ -188,6 +137,8 @@ static LONG WINAPI TopLevelExceptionFilter(struct _EXCEPTION_POINTERS *Exception
|
|||||||
log_warning("signal", "failed to print callstack");
|
log_warning("signal", "failed to print callstack");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deferredlogs::dump_to_logger();
|
||||||
|
|
||||||
if (MiniDumpWriteDump_local != nullptr) {
|
if (MiniDumpWriteDump_local != nullptr) {
|
||||||
HANDLE minidump_file = CreateFileA(
|
HANDLE minidump_file = CreateFileA(
|
||||||
"minidump.dmp",
|
"minidump.dmp",
|
||||||
|
|||||||
@@ -9,15 +9,6 @@ namespace launcher::signal {
|
|||||||
extern bool DISABLE;
|
extern bool DISABLE;
|
||||||
extern bool USE_VEH_WORKAROUND;
|
extern bool USE_VEH_WORKAROUND;
|
||||||
|
|
||||||
// error cases
|
|
||||||
extern bool SUPERSTEP_SOUND_ERROR;
|
|
||||||
extern bool AVS_DIR_CREATION_FAILURE;
|
|
||||||
extern std::string AVS_XML_PATH;
|
|
||||||
extern std::string AVS_SRC_PATH;
|
|
||||||
extern bool D3D9_CREATE_DEVICE_FAILED;
|
|
||||||
extern uint32_t D3D9_CREATE_DEVICE_FAILED_HRESULT;
|
|
||||||
|
|
||||||
//void print_stacktrace();
|
|
||||||
void attach();
|
void attach();
|
||||||
void init();
|
void init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "deferlog.h"
|
||||||
|
#include "util/logging.h"
|
||||||
|
|
||||||
|
namespace deferredlogs {
|
||||||
|
|
||||||
|
const std::initializer_list<std::string> SUPERSTEP_SOUND_ERROR_MESSAGE = {
|
||||||
|
"audio initialization error was previously detected during boot!",
|
||||||
|
" (W:SuperstepSound: Audio device is not available!!!)",
|
||||||
|
" this crash is most likely related to audio init failure",
|
||||||
|
" see if the default audio device changed, fix your audio configuration (e.g., sample rate)",
|
||||||
|
" double check your spice audio options/patches, and try again"
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::vector<std::string>> deferred_errors;
|
||||||
|
|
||||||
|
void defer_error_messages(std::initializer_list<std::string> messages) {
|
||||||
|
deferred_errors.emplace_back(messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_to_logger() {
|
||||||
|
static std::once_flag printed;
|
||||||
|
std::call_once(printed, []() {
|
||||||
|
if (!deferred_errors.empty()) {
|
||||||
|
log_warning("deferred_error",
|
||||||
|
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
log_warning("deferred_error", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto messages : deferred_errors) {
|
||||||
|
for (auto message : messages) {
|
||||||
|
log_warning("deferred_error", "{}", message);
|
||||||
|
}
|
||||||
|
log_warning("deferred_error", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deferred_errors.empty()) {
|
||||||
|
log_warning("deferred_error",
|
||||||
|
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <initializer_list>
|
||||||
|
|
||||||
|
namespace deferredlogs {
|
||||||
|
|
||||||
|
// some shared error messages
|
||||||
|
extern const std::initializer_list<std::string> SUPERSTEP_SOUND_ERROR_MESSAGE;
|
||||||
|
|
||||||
|
void defer_error_messages(std::initializer_list<std::string> messages);
|
||||||
|
void dump_to_logger();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user