diff options
author | Aaron Giles <aaron@aarongiles.com> | 2008-04-20 22:29:29 +0000 |
---|---|---|
committer | Aaron Giles <aaron@aarongiles.com> | 2008-04-20 22:29:29 +0000 |
commit | e0533ec7c3ba33667ac4dd7e435d4024243f0242 (patch) | |
tree | e939d6ac802dac33da0ffb940f11950ee0cdf893 /src/osd/windows/winmain.c | |
parent | 682265e4804d118752ca493e0aeaa2cb0d57421b (diff) |
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.
Diffstat (limited to 'src/osd/windows/winmain.c')
-rw-r--r-- | src/osd/windows/winmain.c | 62 |
1 files changed, 58 insertions, 4 deletions
diff --git a/src/osd/windows/winmain.c b/src/osd/windows/winmain.c index 427482f465c..1f0558dff60 100644 --- a/src/osd/windows/winmain.c +++ b/src/osd/windows/winmain.c @@ -65,7 +65,6 @@ typedef BOOL (WINAPI *av_revert_mm_thread_characteristics_ptr)(HANDLE AvrtHandle int _CRT_glob = 0; - //============================================================ // 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 LPTOP_LEVEL_EXCEPTION_FILTER pass_thru_filter; +static HANDLE watchdog_exit_event; +static HANDLE watchdog_thread; + + #ifndef MESS static const TCHAR helpfile[] = TEXT("docs\\windows.txt"); #else @@ -101,6 +104,7 @@ static void osd_exit(running_machine *machine); static void soft_link_functions(void); 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 const char *lookup_symbol(UINT32 address); static int get_code_base_size(UINT32 *base, UINT32 *size); @@ -120,6 +124,7 @@ const options_entry mame_win_options[] = // debugging options { NULL, NULL, OPTION_HEADER, "WINDOWS DEBUGGING OPTIONS" }, { "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 { NULL, NULL, OPTION_HEADER, "WINDOWS PERFORMANCE OPTIONS" }, @@ -239,9 +244,10 @@ int main(int argc, char **argv) // soft-link optional functions soft_link_functions(); + // compute the name of the mapfile strcpy(mapfile_name, argv[0]); ext = strchr(mapfile_name, '.'); - if (ext) + if (ext != NULL) strcpy(ext, ".map"); else strcat(mapfile_name, ".map"); @@ -267,6 +273,8 @@ static void output_oslog(running_machine *machine, const char *buffer) void osd_init(running_machine *machine) { + int watchdog = options_get_int(mame_options(), WINOPTION_WATCHDOG); + // thread priority if (!options_get_bool(mame_options(), OPTION_DEBUG)) 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); 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) { + // 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(); // turn off our multimedia tasks @@ -361,6 +391,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 //============================================================ @@ -550,13 +596,14 @@ static const char *lookup_symbol(UINT32 address) // parse the file, looking for map entries 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 (addr <= address && addr > best_addr) { best_addr = addr; strcpy(best_symbol, symbol); } + fclose(map); // create the final result 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"); char line[1024]; + int result = 0; // if no file, return nothing if (map == NULL) @@ -584,8 +632,12 @@ static int get_code_base_size(UINT32 *base, UINT32 *size) while (fgets(line, sizeof(line) - 1, map)) if (!strncmp(line, ".text 0x", 18)) if (sscanf(line, ".text 0x%08x 0x%x", base, size) == 2) - return 1; + { + result = 1; + break; + } + fclose(map); return 0; } @@ -625,6 +677,8 @@ static HANDLE profiler_thread; static DWORD profiler_thread_id; static volatile UINT8 profiler_thread_exit; + + //============================================================ // compare_base // compare_hits -- qsort callbacks to sort on |