Add exception handling for Windows

This commit is contained in:
Jupeyy 2022-02-18 10:46:05 +01:00
parent c8363bc96f
commit 4330ff83cf
6 changed files with 104 additions and 0 deletions

View file

@ -117,6 +117,8 @@ option(DISCORD_DYNAMIC "Enable discovering Discord rich presence libraries at ru
option(PREFER_BUNDLED_LIBS "Prefer bundled libraries over system libraries" ${AUTO_DEPENDENCIES_DEFAULT})
option(DEV "Don't generate stuff necessary for packaging" OFF)
option(EXCEPTION_HANDLING "Enable exception handling (only works with Windows as of now)" OFF)
if(TEST_MYSQL)
set(MYSQL ON)
endif()
@ -217,6 +219,10 @@ if(NOT MSVC AND NOT HAIKU)
add_c_compiler_flag_if_supported(OUR_FLAGS -stdlib=libc++)
endif()
if(EXCEPTION_HANDLING)
add_c_compiler_flag_if_supported(OUR_FLAGS -DCONF_EXCEPTION_HANDLING)
endif()
add_c_compiler_flag_if_supported(OUR_FLAGS_OWN -Wall)
if(CMAKE_VERSION VERSION_GREATER 3.3 OR CMAKE_VERSION VERSION_EQUAL 3.3)
add_c_compiler_flag_if_supported(OUR_FLAGS_OWN
@ -239,6 +245,12 @@ if(NOT MSVC AND NOT HAIKU)
#add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN "-Wuseless-cast")
endif()
if(MSVC)
if(EXCEPTION_HANDLING)
add_c_compiler_flag_if_supported(OUR_FLAGS /DCONF_EXCEPTION_HANDLING)
endif()
endif()
if(NOT MSVC AND NOT HAIKU)
check_c_compiler_flag("-O2;-Wp,-Werror;-D_FORTIFY_SOURCE=2" DEFINE_FORTIFY_SOURCE) # Some distributions define _FORTIFY_SOURCE by themselves.
endif()
@ -440,6 +452,10 @@ else()
set(WEBSOCKETS_INCLUDE_DIRS)
endif()
if(EXCEPTION_HANDLING)
find_package(ExceptionHandling)
endif()
if(TARGET_OS AND TARGET_OS STREQUAL "mac")
find_program(CMAKE_OTOOL otool)
find_program(DMGBUILD dmgbuild)
@ -1399,6 +1415,7 @@ set(COPY_FILES
${FFMPEG_COPY_FILES}
${WEBSOCKETS_COPY_FILES}
${DISCORDSDK_COPY_FILES}
${EXCEPTION_HANDLING_COPY_FILES}
)
file(COPY ${COPY_FILES} DESTINATION .)

View file

@ -0,0 +1,21 @@
if(TARGET_OS STREQUAL "windows")
set_extra_dirs_lib(EXCEPTION_HANDLING exception_handling)
find_file(EXCEPTION_HANDLING_LIBRARY
NAMES exchndl.dll
HINTS ${HINTS_EXCEPTION_HANDLING_LIBDIR}
PATHS ${PATHS_EXCEPTION_HANDLING_LIBDIR}
${CROSSCOMPILING_NO_CMAKE_SYSTEM_PATH}
)
is_bundled(EXCEPTION_HANDLING_BUNDLED "${EXCEPTION_HANDLING_LIBRARY}")
if(NOT EXCEPTION_HANDLING_BUNDLED)
message(FATAL_ERROR "could not find exception handling paths")
endif()
set(EXCEPTION_HANDLING_COPY_FILES
"${EXTRA_EXCEPTION_HANDLING_LIBDIR}/exchndl.dll"
"${EXTRA_EXCEPTION_HANDLING_LIBDIR}/dbgcore.dll"
"${EXTRA_EXCEPTION_HANDLING_LIBDIR}/dbghelp.dll"
"${EXTRA_EXCEPTION_HANDLING_LIBDIR}/mgwhelp.dll"
"${EXTRA_EXCEPTION_HANDLING_LIBDIR}/symsrv.dll"
)
endif()

View file

@ -4060,4 +4060,37 @@ int os_version_str(char *version, int length)
return 0;
#endif
}
#if defined(CONF_EXCEPTION_HANDLING)
#if defined(CONF_FAMILY_WINDOWS)
static HMODULE gs_ExceptionHandlingModule = nullptr;
#endif
void init_exception_handler()
{
#if defined(CONF_FAMILY_WINDOWS)
gs_ExceptionHandlingModule = LoadLibraryA("exchndl.dll");
if(gs_ExceptionHandlingModule != nullptr)
{
auto pfnExcHndlInit = (void APIENTRY (*)())GetProcAddress(gs_ExceptionHandlingModule, "ExcHndlInit");
pfnExcHndlInit();
}
#else
#error exception handling not implemented
#endif
}
void set_exception_handler_log_file(const char *pLogFilePath)
{
#if defined(CONF_FAMILY_WINDOWS)
if(gs_ExceptionHandlingModule != nullptr)
{
auto pExceptionLogFilePathFunc = (BOOL APIENTRY(*)(const char *))(GetProcAddress(gs_ExceptionHandlingModule, "ExcHndlSetLogFileNameA"));
pExceptionLogFilePathFunc(pLogFilePath);
}
#else
#error exception handling not implemented
#endif
}
#endif
}

View file

@ -2368,6 +2368,11 @@ void set_console_msg_color(const void *rgbvoid);
*/
int os_version_str(char *version, int length);
#if defined(CONF_EXCEPTION_HANDLING)
void init_exception_handler();
void set_exception_handler_log_file(const char *pLogFilePath);
#endif
#if defined(__cplusplus)
}
#endif

View file

@ -4268,6 +4268,10 @@ int main(int argc, const char **argv)
InitAndroid();
#endif
#if defined(CONF_EXCEPTION_HANDLING)
init_exception_handler();
#endif
if(secure_random_init() != 0)
{
RandInitFailed = true;
@ -4292,6 +4296,16 @@ int main(int argc, const char **argv)
IDiscord *pDiscord = CreateDiscord();
ISteam *pSteam = CreateSteam();
#if defined(CONF_EXCEPTION_HANDLING)
char aBuf[IO_MAX_PATH_LENGTH];
char aBufName[IO_MAX_PATH_LENGTH];
char aDate[64];
str_timestamp(aDate, sizeof(aDate));
str_format(aBufName, sizeof(aBufName), "dumps/" GAME_NAME "_crash_log_%d_%s.RTP", pid(), aDate);
pStorage->GetCompletePath(IStorage::TYPE_SAVE, aBufName, aBuf, sizeof(aBuf));
set_exception_handler_log_file(aBuf);
#endif
if(RandInitFailed)
{
dbg_msg("secure", "could not initialize secure RNG");

View file

@ -3645,6 +3645,10 @@ int main(int argc, const char **argv)
signal(SIGINT, HandleSigIntTerm);
signal(SIGTERM, HandleSigIntTerm);
#if defined(CONF_EXCEPTION_HANDLING)
init_exception_handler();
#endif
CServer *pServer = CreateServer();
IKernel *pKernel = IKernel::Create();
@ -3658,6 +3662,16 @@ int main(int argc, const char **argv)
IConfigManager *pConfigManager = CreateConfigManager();
IEngineAntibot *pEngineAntibot = CreateEngineAntibot();
#if defined(CONF_EXCEPTION_HANDLING)
char aBuf[IO_MAX_PATH_LENGTH];
char aBufName[IO_MAX_PATH_LENGTH];
char aDate[64];
str_timestamp(aDate, sizeof(aDate));
str_format(aBufName, sizeof(aBufName), "dumps/" GAME_NAME "-Server_crash_log_%d_%s.RTP", pid(), aDate);
pStorage->GetCompletePath(IStorage::TYPE_SAVE, aBufName, aBuf, sizeof(aBuf));
set_exception_handler_log_file(aBuf);
#endif
pServer->InitRegister(&pServer->m_NetServer, pEngineMasterServer, pConfigManager->Values(), pConsole);
{