static int DoSysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps ) { if( eps->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION ) return EXCEPTION_CONTINUE_SEARCH; // Note: This exception can be accessed by the EE or MTVU thread // Source_PageFault is a global variable with its own state information // so for now we lock this exception code unless someone can fix this better... Threading::ScopedLock lock(PageFault_Mutex); Source_PageFault->Dispatch( PageFaultInfo( (uptr)eps->ExceptionRecord->ExceptionInformation[1] ) ); return Source_PageFault->WasHandled() ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH; }
// Linux implementation of SIGSEGV handler. Bind it using sigaction(). static void SysPageFaultSignalFilter( int signal, siginfo_t *siginfo, void * ) { // [TODO] : Add a thread ID filter to the Linux Signal handler here. // Rationale: On windows, the __try/__except model allows per-thread specific behavior // for page fault handling. On linux, there is a single signal handler for the whole // process, but the handler is executed by the thread that caused the exception. // Stdio Usage note: SIGSEGV handling is a synchronous in-thread signal. It is done // from the context of the current thread and stackframe. So long as the thread is not // the main/ui thread, use of the px assertion system should be safe. Use of stdio should // be safe even on the main thread. // (in other words, stdio limitations only really apply to process-level asynchronous // signals) // Note: Use of stdio functions isn't safe here. Avoid console logs, // assertions, file logs, or just about anything else useful. // Note: This signal can be accessed by the EE or MTVU thread // Source_PageFault is a global variable with its own state information // so for now we lock this exception code unless someone can fix this better... Threading::ScopedLock lock(PageFault_Mutex); Source_PageFault->Dispatch( PageFaultInfo( (uptr)siginfo->si_addr & ~m_pagemask ) ); // resumes execution right where we left off (re-executes instruction that // caused the SIGSEGV). if (Source_PageFault->WasHandled()) return; if (!wxThread::IsMain()) { pxFailRel(pxsFmt("Unhandled page fault @ 0x%08x", siginfo->si_addr)); } // Bad mojo! Completely invalid address. // Instigate a trap if we're in a debugger, and if not then do a SIGKILL. wxTrap(); if (!IsDebugBuild) raise( SIGKILL ); }