mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2025-02-17 19:19:16 +01:00
util: Add signal module introducing signal and exception handling
Right now, this prints to the console using the util/log logger only. Stacktrace on exception still needs to be added.
This commit is contained in:
parent
beea9e7bb7
commit
1d25abc10b
@ -13,6 +13,7 @@ src_util := \
|
||||
mem.c \
|
||||
msg-thread.c \
|
||||
net.c \
|
||||
signal.c \
|
||||
str.c \
|
||||
thread.c \
|
||||
time.c \
|
||||
|
131
src/main/util/signal.c
Normal file
131
src/main/util/signal.c
Normal file
@ -0,0 +1,131 @@
|
||||
#include <unistd.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "util/hex.h"
|
||||
#include "util/log.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
static signal_shutdown_handler_t shutdown_handler;
|
||||
|
||||
static const char* control_code_to_str(DWORD ctrl_code) {
|
||||
switch (ctrl_code) {
|
||||
case CTRL_C_EVENT:
|
||||
return "CTRL_C_EVENT";
|
||||
case CTRL_BREAK_EVENT:
|
||||
return "CTRL_BREAK_EVENT";
|
||||
case CTRL_CLOSE_EVENT:
|
||||
return "CTRL_CLOSE_EVENT";
|
||||
case CTRL_LOGOFF_EVENT:
|
||||
return "CTRL_LOGOFF_EVENT";
|
||||
case CTRL_SHUTDOWN_EVENT:
|
||||
return "CTRL_SHUTDOWN_EVENT";
|
||||
default:
|
||||
log_warning("Unknown control code: %lX", ctrl_code);
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static const char* exception_code_to_str(struct _EXCEPTION_RECORD *exception_record) {
|
||||
switch (exception_record->ExceptionCode) {
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
return "EXCEPTION_ACCESS_VIOLATION";
|
||||
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
|
||||
return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
|
||||
case EXCEPTION_BREAKPOINT:
|
||||
return "EXCEPTION_BREAKPOINT";
|
||||
case EXCEPTION_DATATYPE_MISALIGNMENT:
|
||||
return "EXCEPTION_DATATYPE_MISALIGNMENT";
|
||||
case EXCEPTION_FLT_DENORMAL_OPERAND:
|
||||
return "EXCEPTION_FLT_DENORMAL_OPERAND";
|
||||
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
|
||||
return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
|
||||
case EXCEPTION_FLT_INEXACT_RESULT:
|
||||
return "EXCEPTION_FLT_INEXACT_RESULT";
|
||||
case EXCEPTION_FLT_INVALID_OPERATION:
|
||||
return "EXCEPTION_FLT_INVALID_OPERATION";
|
||||
case EXCEPTION_FLT_OVERFLOW:
|
||||
return "EXCEPTION_FLT_OVERFLOW";
|
||||
case EXCEPTION_FLT_STACK_CHECK:
|
||||
return "EXCEPTION_FLT_STACK_CHECK";
|
||||
case EXCEPTION_FLT_UNDERFLOW:
|
||||
return "EXCEPTION_FLT_UNDERFLOW";
|
||||
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
||||
return "EXCEPTION_ILLEGAL_INSTRUCTION";
|
||||
case EXCEPTION_IN_PAGE_ERROR:
|
||||
return "EXCEPTION_IN_PAGE_ERROR";
|
||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||
return "EXCEPTION_INT_DIVIDE_BY_ZERO";
|
||||
case EXCEPTION_INT_OVERFLOW:
|
||||
return "EXCEPTION_INT_OVERFLOW";
|
||||
case EXCEPTION_INVALID_DISPOSITION:
|
||||
return "EXCEPTION_INVALID_DISPOSITION";
|
||||
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
|
||||
return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
|
||||
case EXCEPTION_PRIV_INSTRUCTION:
|
||||
return "EXCEPTION_PRIV_INSTRUCTION";
|
||||
case EXCEPTION_SINGLE_STEP:
|
||||
return "EXCEPTION_SINGLE_STEP";
|
||||
case EXCEPTION_STACK_OVERFLOW:
|
||||
return "EXCEPTION_STACK_OVERFLOW";
|
||||
case DBG_CONTROL_C:
|
||||
return "DBG_CONTROL_C";
|
||||
default:
|
||||
log_warning("Unknown exception code: %lX", exception_record->ExceptionCode);
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL WINAPI console_ctrl_handler(DWORD dwCtrlType) {
|
||||
log_misc("Console ctrl handler called: %s", control_code_to_str(dwCtrlType));
|
||||
|
||||
if (dwCtrlType == CTRL_C_EVENT) {
|
||||
if (shutdown_handler) {
|
||||
log_misc("Executing shutdown handler");
|
||||
shutdown_handler();
|
||||
}
|
||||
|
||||
log_info("Exiting process");
|
||||
|
||||
ExitProcess(0);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static LONG WINAPI unhandled_exception_filter(struct _EXCEPTION_POINTERS *ExceptionInfo) {
|
||||
|
||||
// no exception info provided
|
||||
if (ExceptionInfo != NULL) {
|
||||
struct _EXCEPTION_RECORD *ExceptionRecord = ExceptionInfo->ExceptionRecord;
|
||||
|
||||
log_warning("Exception raised: %s", exception_code_to_str(ExceptionRecord));
|
||||
|
||||
struct _EXCEPTION_RECORD *record_cause = ExceptionRecord->ExceptionRecord;
|
||||
|
||||
while (record_cause != NULL) {
|
||||
log_warning("Caused by: %s", exception_code_to_str(record_cause));
|
||||
record_cause = record_cause->ExceptionRecord;
|
||||
}
|
||||
|
||||
// TODO print stacktrace
|
||||
|
||||
log_fatal("End exception handler");
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
void signal_exception_handler_init()
|
||||
{
|
||||
SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
|
||||
SetUnhandledExceptionFilter(unhandled_exception_filter);
|
||||
|
||||
log_info("Initialized");
|
||||
}
|
||||
|
||||
void signal_register_shutdown_handler(signal_shutdown_handler_t handler)
|
||||
{
|
||||
shutdown_handler = handler;
|
||||
|
||||
log_misc("Registered shutdown handler");
|
||||
}
|
20
src/main/util/signal.h
Normal file
20
src/main/util/signal.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Function signature of shutdown handler.
|
||||
*/
|
||||
typedef void (*signal_shutdown_handler_t)();
|
||||
|
||||
/**
|
||||
* Initialize signal and exception handlers. Exceptions and signals, are logged using the logger
|
||||
* to create visibility.
|
||||
*/
|
||||
void signal_exception_handler_init();
|
||||
|
||||
/**
|
||||
* Register a handler function that gets called when the application is supposed to shut down,
|
||||
* e.g. on CTRL + C.
|
||||
*
|
||||
* @param handler Handler function to register.
|
||||
*/
|
||||
void signal_register_shutdown_handler(signal_shutdown_handler_t handler);
|
Loading…
x
Reference in New Issue
Block a user