mirror of
https://github.com/holub/mame
synced 2025-04-29 11:30:28 +03:00
Added new Windows option -watchdog, which creates a watchdog thread
that forcibly kills the application after a certain number of seconds. Primarily intended to be used in regression test runs to handle the occasional hung game.
This commit is contained in:
parent
682265e480
commit
e0533ec7c3
@ -65,7 +65,6 @@ typedef BOOL (WINAPI *av_revert_mm_thread_characteristics_ptr)(HANDLE AvrtHandle
|
|||||||
int _CRT_glob = 0;
|
int _CRT_glob = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// LOCAL VARIABLES
|
// LOCAL VARIABLES
|
||||||
//============================================================
|
//============================================================
|
||||||
@ -79,6 +78,10 @@ static av_revert_mm_thread_characteristics_ptr av_revert_mm_thread_characteristi
|
|||||||
static char mapfile_name[MAX_PATH];
|
static char mapfile_name[MAX_PATH];
|
||||||
static LPTOP_LEVEL_EXCEPTION_FILTER pass_thru_filter;
|
static LPTOP_LEVEL_EXCEPTION_FILTER pass_thru_filter;
|
||||||
|
|
||||||
|
static HANDLE watchdog_exit_event;
|
||||||
|
static HANDLE watchdog_thread;
|
||||||
|
|
||||||
|
|
||||||
#ifndef MESS
|
#ifndef MESS
|
||||||
static const TCHAR helpfile[] = TEXT("docs\\windows.txt");
|
static const TCHAR helpfile[] = TEXT("docs\\windows.txt");
|
||||||
#else
|
#else
|
||||||
@ -101,6 +104,7 @@ static void osd_exit(running_machine *machine);
|
|||||||
|
|
||||||
static void soft_link_functions(void);
|
static void soft_link_functions(void);
|
||||||
static int is_double_click_start(int argc);
|
static int is_double_click_start(int argc);
|
||||||
|
static DWORD WINAPI watchdog_thread_entry(LPVOID lpParameter);
|
||||||
static LONG CALLBACK exception_filter(struct _EXCEPTION_POINTERS *info);
|
static LONG CALLBACK exception_filter(struct _EXCEPTION_POINTERS *info);
|
||||||
static const char *lookup_symbol(UINT32 address);
|
static const char *lookup_symbol(UINT32 address);
|
||||||
static int get_code_base_size(UINT32 *base, UINT32 *size);
|
static int get_code_base_size(UINT32 *base, UINT32 *size);
|
||||||
@ -120,6 +124,7 @@ const options_entry mame_win_options[] =
|
|||||||
// debugging options
|
// debugging options
|
||||||
{ NULL, NULL, OPTION_HEADER, "WINDOWS DEBUGGING OPTIONS" },
|
{ NULL, NULL, OPTION_HEADER, "WINDOWS DEBUGGING OPTIONS" },
|
||||||
{ "oslog", "0", OPTION_BOOLEAN, "output error.log data to the system debugger" },
|
{ "oslog", "0", OPTION_BOOLEAN, "output error.log data to the system debugger" },
|
||||||
|
{ "watchdog;wdog", "0", 0, "force the program to terminate if no updates within specified number of seconds" },
|
||||||
|
|
||||||
// performance options
|
// performance options
|
||||||
{ NULL, NULL, OPTION_HEADER, "WINDOWS PERFORMANCE OPTIONS" },
|
{ NULL, NULL, OPTION_HEADER, "WINDOWS PERFORMANCE OPTIONS" },
|
||||||
@ -239,9 +244,10 @@ int main(int argc, char **argv)
|
|||||||
// soft-link optional functions
|
// soft-link optional functions
|
||||||
soft_link_functions();
|
soft_link_functions();
|
||||||
|
|
||||||
|
// compute the name of the mapfile
|
||||||
strcpy(mapfile_name, argv[0]);
|
strcpy(mapfile_name, argv[0]);
|
||||||
ext = strchr(mapfile_name, '.');
|
ext = strchr(mapfile_name, '.');
|
||||||
if (ext)
|
if (ext != NULL)
|
||||||
strcpy(ext, ".map");
|
strcpy(ext, ".map");
|
||||||
else
|
else
|
||||||
strcat(mapfile_name, ".map");
|
strcat(mapfile_name, ".map");
|
||||||
@ -267,6 +273,8 @@ static void output_oslog(running_machine *machine, const char *buffer)
|
|||||||
|
|
||||||
void osd_init(running_machine *machine)
|
void osd_init(running_machine *machine)
|
||||||
{
|
{
|
||||||
|
int watchdog = options_get_int(mame_options(), WINOPTION_WATCHDOG);
|
||||||
|
|
||||||
// thread priority
|
// thread priority
|
||||||
if (!options_get_bool(mame_options(), OPTION_DEBUG))
|
if (!options_get_bool(mame_options(), OPTION_DEBUG))
|
||||||
SetThreadPriority(GetCurrentThread(), options_get_int(mame_options(), WINOPTION_PRIORITY));
|
SetThreadPriority(GetCurrentThread(), options_get_int(mame_options(), WINOPTION_PRIORITY));
|
||||||
@ -295,11 +303,33 @@ void osd_init(running_machine *machine)
|
|||||||
// mm_task = (*av_set_mm_thread_characteristics)(TEXT("Playback"), &task_index);
|
// mm_task = (*av_set_mm_thread_characteristics)(TEXT("Playback"), &task_index);
|
||||||
|
|
||||||
start_profiler();
|
start_profiler();
|
||||||
|
|
||||||
|
// if a watchdog thread is requested, create one
|
||||||
|
if (watchdog != 0)
|
||||||
|
{
|
||||||
|
watchdog_exit_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
|
assert_always(watchdog_exit_event != NULL, "Failed to create watchdog event");
|
||||||
|
watchdog_thread = CreateThread(NULL, 0, watchdog_thread_entry, (LPVOID)watchdog, 0, NULL);
|
||||||
|
assert_always(watchdog_thread != NULL, "Failed to create watchdog thread");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================
|
||||||
|
// osd_exit
|
||||||
|
//============================================================
|
||||||
|
|
||||||
static void osd_exit(running_machine *machine)
|
static void osd_exit(running_machine *machine)
|
||||||
{
|
{
|
||||||
|
// take down the watchdog thread if it exists
|
||||||
|
if (watchdog_thread != NULL)
|
||||||
|
{
|
||||||
|
SetEvent(watchdog_exit_event);
|
||||||
|
WaitForSingleObject(watchdog_thread, INFINITE);
|
||||||
|
watchdog_exit_event = NULL;
|
||||||
|
watchdog_thread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
stop_profiler();
|
stop_profiler();
|
||||||
|
|
||||||
// turn off our multimedia tasks
|
// turn off our multimedia tasks
|
||||||
@ -360,6 +390,22 @@ static int is_double_click_start(int argc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================
|
||||||
|
// watchdog_thread_entry
|
||||||
|
//============================================================
|
||||||
|
|
||||||
|
static DWORD WINAPI watchdog_thread_entry(LPVOID lpParameter)
|
||||||
|
{
|
||||||
|
DWORD timeout = (int)(FPTR)lpParameter * 1000;
|
||||||
|
DWORD wait_result;
|
||||||
|
|
||||||
|
wait_result = WaitForSingleObject(watchdog_exit_event, timeout);
|
||||||
|
if (wait_result == WAIT_TIMEOUT)
|
||||||
|
TerminateProcess(GetCurrentProcess(), -1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// exception_filter
|
// exception_filter
|
||||||
//============================================================
|
//============================================================
|
||||||
@ -550,13 +596,14 @@ static const char *lookup_symbol(UINT32 address)
|
|||||||
|
|
||||||
// parse the file, looking for map entries
|
// parse the file, looking for map entries
|
||||||
while (fgets(line, sizeof(line) - 1, map))
|
while (fgets(line, sizeof(line) - 1, map))
|
||||||
if (!strncmp(line, " 0x", 18))
|
if (strncmp(line, " 0x", 18) == 0)
|
||||||
if (sscanf(line, " 0x%08x %s", &addr, symbol) == 2)
|
if (sscanf(line, " 0x%08x %s", &addr, symbol) == 2)
|
||||||
if (addr <= address && addr > best_addr)
|
if (addr <= address && addr > best_addr)
|
||||||
{
|
{
|
||||||
best_addr = addr;
|
best_addr = addr;
|
||||||
strcpy(best_symbol, symbol);
|
strcpy(best_symbol, symbol);
|
||||||
}
|
}
|
||||||
|
fclose(map);
|
||||||
|
|
||||||
// create the final result
|
// create the final result
|
||||||
if (address - best_addr > 0x10000)
|
if (address - best_addr > 0x10000)
|
||||||
@ -575,6 +622,7 @@ static int get_code_base_size(UINT32 *base, UINT32 *size)
|
|||||||
{
|
{
|
||||||
FILE * map = fopen(mapfile_name, "r");
|
FILE * map = fopen(mapfile_name, "r");
|
||||||
char line[1024];
|
char line[1024];
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
// if no file, return nothing
|
// if no file, return nothing
|
||||||
if (map == NULL)
|
if (map == NULL)
|
||||||
@ -584,8 +632,12 @@ static int get_code_base_size(UINT32 *base, UINT32 *size)
|
|||||||
while (fgets(line, sizeof(line) - 1, map))
|
while (fgets(line, sizeof(line) - 1, map))
|
||||||
if (!strncmp(line, ".text 0x", 18))
|
if (!strncmp(line, ".text 0x", 18))
|
||||||
if (sscanf(line, ".text 0x%08x 0x%x", base, size) == 2)
|
if (sscanf(line, ".text 0x%08x 0x%x", base, size) == 2)
|
||||||
return 1;
|
{
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(map);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,6 +677,8 @@ static HANDLE profiler_thread;
|
|||||||
static DWORD profiler_thread_id;
|
static DWORD profiler_thread_id;
|
||||||
static volatile UINT8 profiler_thread_exit;
|
static volatile UINT8 profiler_thread_exit;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// compare_base
|
// compare_base
|
||||||
// compare_hits -- qsort callbacks to sort on
|
// compare_hits -- qsort callbacks to sort on
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#define WINOPTION_AUDIO_LATENCY "audio_latency"
|
#define WINOPTION_AUDIO_LATENCY "audio_latency"
|
||||||
#define WINOPTION_PRIORITY "priority"
|
#define WINOPTION_PRIORITY "priority"
|
||||||
#define WINOPTION_MULTITHREADING "multithreading"
|
#define WINOPTION_MULTITHREADING "multithreading"
|
||||||
|
#define WINOPTION_WATCHDOG "watchdog"
|
||||||
#define WINOPTION_OSLOG "oslog"
|
#define WINOPTION_OSLOG "oslog"
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user