diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs index 557efe15c0..a808455764 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/SNES/LibsnesApi.cs @@ -34,6 +34,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES string InstanceName; Process process; + System.Threading.EventWaitHandle watchdogEvent; NamedPipeServerStream pipe; BinaryWriter bwPipe; BinaryReader brPipe; @@ -96,6 +97,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES pipe = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.None, 1024 * 1024, 1024); + //slim chance this might be useful sometimes: + //http://stackoverflow.com/questions/2590334/creating-a-cross-process-eventwaithandle + //create an event for the child process to monitor with a watchdog, to make sure it terminates when the emuhawk process terminates. + //NOTE: this is alarming! for some reason .net releases this event when it gets finalized, instead of when i (dont) dispose it. + bool createdNew; + watchdogEvent = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.AutoReset, InstanceName + "-event", out createdNew); + process = new Process(); process.StartInfo.WorkingDirectory = Path.GetDirectoryName(exePath); process.StartInfo.FileName = exePath; @@ -134,6 +142,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES public void Dispose() { + watchdogEvent.Dispose(); process.Kill(); process.Dispose(); process = null; diff --git a/libsnes/bsnes/target-libsnes/libsnes_pwrap.cpp b/libsnes/bsnes/target-libsnes/libsnes_pwrap.cpp index 2062c27459..0a5b260ea8 100644 --- a/libsnes/bsnes/target-libsnes/libsnes_pwrap.cpp +++ b/libsnes/bsnes/target-libsnes/libsnes_pwrap.cpp @@ -342,10 +342,51 @@ public: } }; //class IPCRingBuffer + +class Watchdog +{ +public: + void Start(const char* _eventName) + { + HANDLE thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)&ThreadProc, this, 0, NULL); + SetThreadPriority(thread,THREAD_PRIORITY_LOWEST); + eventName = _eventName; + } + +private: + + std::string eventName; + + + static DWORD ThreadProc(LPVOID lpParam) + { + Watchdog* w = (Watchdog*)lpParam; + for(;;) + { + //only check once per second + Sleep(1000); + + //try opening the handle. if its gone, the process is gone + HANDLE hEvent = OpenEvent(SYNCHRONIZE | EVENT_ALL_ACCESS, FALSE, w->eventName.c_str()); + + //printf("event handle: %08X (%d)\n",hEvent,hEvent?0:GetLastError()); //debugging + + //handle was gone, terminate process + if(hEvent == 0) + { + TerminateProcess(INVALID_HANDLE_VALUE,0); + } + + CloseHandle(hEvent); + } + } +}; //class Watchdog + static bool bufio = false; static IPCRingBuffer *rbuf = NULL, *wbuf = NULL; -HANDLE hPipe, hMapFile; +Watchdog s_Watchdog; +HANDLE hPipe, hMapFile, hEvent; void* hMapFilePtr; static bool running = false; @@ -1199,7 +1240,9 @@ int xmain(int argc, char** argv) } char pipename[256]; + char eventname[256]; sprintf(pipename, "\\\\.\\Pipe\\%s",argv[1]); + sprintf(eventname, "%s-event",argv[1]); if(!strncmp(argv[1],"console",7)) { @@ -1207,6 +1250,9 @@ int xmain(int argc, char** argv) } printf("pipe: %s\n",pipename); + printf("event: %s\n",eventname); + + s_Watchdog.Start(eventname); hPipe = CreateFile(pipename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); diff --git a/output/dll/libsneshawk-32-compatibility.exe b/output/dll/libsneshawk-32-compatibility.exe index 36f605468c..06a438ea5b 100644 Binary files a/output/dll/libsneshawk-32-compatibility.exe and b/output/dll/libsneshawk-32-compatibility.exe differ diff --git a/output/dll/libsneshawk-32-performance.exe b/output/dll/libsneshawk-32-performance.exe index 728874098d..fc856c9d4d 100644 Binary files a/output/dll/libsneshawk-32-performance.exe and b/output/dll/libsneshawk-32-performance.exe differ