void CrashHandlerImpl::processCrash(const std::string & sharedMemoryName) {
	
	try {
		
		m_SharedMemoryName = sharedMemoryName;
		
		// Create a shared memory object.
		m_SharedMemory = bip::shared_memory_object(bip::open_only, m_SharedMemoryName.c_str(),
		                                           bip::read_write);
		
		// Map the whole shared memory in this process
		m_MemoryMappedRegion = bip::mapped_region(m_SharedMemory, bip::read_write);
		
		// Our SharedCrashInfo will be stored in this shared memory.
		m_pCrashInfo = reinterpret_cast<CrashInfo *>(m_MemoryMappedRegion.get_address());
		if(m_pCrashInfo) {
			m_textLength = std::find(m_pCrashInfo->description, m_pCrashInfo->description
			                         + boost::size(m_pCrashInfo->description), '\0')
			               - m_pCrashInfo->description;
		}
		
	} catch(...) {
		// Unexpected error
		m_pCrashInfo = NULL;
	}
	
	processCrash();
	
	std::exit(0);
}
void CrashHandlerWindows::handleCrash(int crashType, void * crashExtraInfo, int fpeCode) {
	
	Autolock autoLock(&m_Lock);
	
	// Run the callbacks
	for(std::vector<CrashHandler::CrashCallback>::iterator it = m_crashCallbacks.begin();
	    it != m_crashCallbacks.end(); ++it) {
		(*it)();
	}
	
	m_pCrashInfo->signal = crashType;
	m_pCrashInfo->code = fpeCode;
	
	PEXCEPTION_POINTERS pointers = reinterpret_cast<PEXCEPTION_POINTERS>(crashExtraInfo);
	
	// Copy CONTEXT to crash info structure
	PCONTEXT context = reinterpret_cast<PCONTEXT>(m_pCrashInfo->contextRecord);
	ARX_STATIC_ASSERT(sizeof(m_pCrashInfo->contextRecord) >= sizeof(*context),
	                  "buffer too small");
	memset(context, 0, sizeof(*context));
	EXCEPTION_POINTERS fakePointers;
	EXCEPTION_RECORD exception;
	if(pointers) {
		u32 code = m_pCrashInfo->exceptionCode = pointers->ExceptionRecord->ExceptionCode;
		m_pCrashInfo->address = u64(pointers->ExceptionRecord->ExceptionAddress);
		m_pCrashInfo->hasAddress = true;
		if(code == EXCEPTION_ACCESS_VIOLATION || code == EXCEPTION_IN_PAGE_ERROR) {
			m_pCrashInfo->memory = pointers->ExceptionRecord->ExceptionInformation[1];
			m_pCrashInfo->hasMemory = true;
		}
		#if ARX_ARCH == ARX_ARCH_X86
		m_pCrashInfo->stack =  pointers->ContextRecord->Esp;
		m_pCrashInfo->hasStack = true;
		m_pCrashInfo->frame =  pointers->ContextRecord->Ebp;
		m_pCrashInfo->hasFrame = true;
		#elif ARX_ARCH == ARX_ARCH_X86_64
		m_pCrashInfo->stack =  pointers->ContextRecord->Rsp;
		m_pCrashInfo->hasStack = true;
		#endif
		std::memcpy(context, pointers->ContextRecord, sizeof(*context));
	} else {
		RtlCaptureContext(context);
		std::memset(&exception, 0, sizeof(exception));
		fakePointers.ContextRecord = context;
		fakePointers.ExceptionRecord = &exception;
		pointers = &fakePointers;
	}
	
	// Get current thread id
	m_pCrashInfo->threadId = u32(GetCurrentThreadId());
	
	writeCrashDump(pointers);
	
	// Try to spawn a sub-process to process the crash info
	STARTUPINFO si;
	memset(&si, 0, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);
	PROCESS_INFORMATION pi;
	memset(&pi, 0, sizeof(PROCESS_INFORMATION));
	BOOL created = CreateProcessW(m_exe, m_args.data(), NULL, NULL, FALSE,
	                              0, NULL, NULL, &si, &pi);
	if(created) {
		while(true) {
			if(m_pCrashInfo->exitLock.try_wait()) {
				break;
			}
			if(WaitForSingleObject(pi.hProcess, 100) != WAIT_TIMEOUT) {
				break;
			}
		}
		TerminateProcess(GetCurrentProcess(), 1);
		unregisterCrashHandlers();
		std::abort();
	}
	
	// Fallback: process the crash info in-process
	unregisterCrashHandlers();
	processCrash();
	
	std::abort();
}
void CrashHandlerPOSIX::handleCrash(int signal, void * info, void * context) {
	
	// Remove crash handlers so we don't end in an infinite crash loop
	removeCrashHandlers(m_pPreviousCrashHandlers);
	
	// Run the callbacks
	for(std::vector<CrashHandler::CrashCallback>::iterator it = m_crashCallbacks.begin();
	    it != m_crashCallbacks.end(); ++it) {
		(*it)();
	}
	
	m_pCrashInfo->signal = signal;
	
	#if ARX_HAVE_SIGACTION
	if(info) {
		siginfo_t * siginfo = reinterpret_cast<siginfo_t *>(info);
		m_pCrashInfo->code = siginfo->si_code;
		#if defined(SIGILL) || defined(SIGFPE)
		if(signal == SIGILL || signal == SIGFPE) {
			m_pCrashInfo->address = u64(siginfo->si_addr);
			m_pCrashInfo->hasAddress = true;
		}
		#endif
		#if defined(SIGSEGV) && defined(SIGBUS)
		if(signal == SIGSEGV || signal == SIGBUS) {
			m_pCrashInfo->memory = u64(siginfo->si_addr);
			m_pCrashInfo->hasMemory = true;
		}
		#endif
	}
	#endif
	
	#if ARX_HAVE_SIGACTION && ARX_PLATFORM == ARX_PLATFORM_LINUX
	if(context) {
		ucontext_t * ctx = reinterpret_cast<ucontext_t *>(context);
		#if ARX_ARCH == ARX_ARCH_X86 && defined(REG_EIP)
		m_pCrashInfo->address = ctx->uc_mcontext.gregs[REG_EIP];
		m_pCrashInfo->hasAddress = true;
		m_pCrashInfo->stack = ctx->uc_mcontext.gregs[REG_ESP];
		m_pCrashInfo->hasStack = true;
		m_pCrashInfo->frame = ctx->uc_mcontext.gregs[REG_EBP];
		m_pCrashInfo->hasFrame = true;
		#elif ARX_ARCH == ARX_ARCH_X86_64 && defined(REG_RIP)
		m_pCrashInfo->address = ctx->uc_mcontext.gregs[REG_RIP];
		m_pCrashInfo->hasAddress = true;
		m_pCrashInfo->stack = ctx->uc_mcontext.gregs[REG_RSP];
		m_pCrashInfo->hasStack = true;
		#elif ARX_ARCH == ARX_ARCH_ARM
		m_pCrashInfo->address =  ctx->uc_mcontext.arm_pc;
		m_pCrashInfo->hasAddress = true;
		m_pCrashInfo->stack =  ctx->uc_mcontext.arm_sp;
		m_pCrashInfo->hasStack = true;
		m_pCrashInfo->frame = ctx->uc_mcontext.arm_fp;
		m_pCrashInfo->hasFrame = true;
		#else
		ARX_UNUSED(ctx);
		#endif
	}
	#else
	ARX_UNUSED(context);
	#endif
	
	// Store the backtrace in the shared crash info
	#if ARX_HAVE_BACKTRACE
	backtrace(m_pCrashInfo->backtrace, boost::size(m_pCrashInfo->backtrace));
	#endif
	
	// Change directory core dumps are written to
	if(m_pCrashInfo->crashReportFolder[0] != '\0') {
		#if ARX_HAVE_CHDIR
		if(chdir(m_pCrashInfo->crashReportFolder) == 0) {
			// Shut up GCC, we don't care
		}
		#endif
	}
	
	// Try to spawn a sub-process to process the crash info
	// Using fork() in a signal handler is bad, but we are already crashing anyway
	pid_t processor = fork();
	if(processor > 0) {
		while(true) {
			if(m_pCrashInfo->exitLock.try_wait()) {
				break;
			}
			#if ARX_HAVE_WAITPID
			if(waitpid(processor, NULL, WNOHANG) != 0) {
				break;
			}
			#endif
			#if ARX_HAVE_NANOSLEEP
			timespec t;
			t.tv_sec = 0;
			t.tv_nsec = 100 * 1000;
			nanosleep(&t, NULL);
			#endif
		}
		// Exit if the crash reporter failed
		kill(getpid(), SIGKILL);
		std::abort();
	}
	#ifdef ARX_HAVE_EXECVP
	char argument[256];
	strcpy(argument, "--crashinfo=");
	strcat(argument, m_SharedMemoryName.c_str());
	const char * args[] = { m_executable.string().c_str(), argument, NULL };
	execvp(m_executable.string().c_str(), const_cast<char **>(args));
	#endif
	
	// Fallback: process the crash info in-process
	processCrash();
	
	std::abort();
}