bool crash_handler::need_write_dump() { if (!is_crash_handle_enabled()) return false; if (get_dump_type() == -1) return false; return true; }
// This method creates minidump of the process void crash_handler::create_mini_dump(EXCEPTION_POINTERS* pExcPtrs) { MINIDUMP_EXCEPTION_INFORMATION mei; MINIDUMP_CALLBACK_INFORMATION mci; // Load dbghelp.dll HMODULE hDbgHelp = LoadLibrary(_T("dbghelp.dll")); if(hDbgHelp == NULL) { // Error - couldn't load dbghelp.dll return; } // create folder if not existed if (!CreateDirectory((get_report_path() + std::wstring(L"\\")).c_str(), NULL) && ERROR_ALREADY_EXISTS != GetLastError()) { return; } create_log_file_for_hockey_app(pExcPtrs); // Create the minidump file HANDLE handleFile (CreateFile( get_report_mini_dump_path().c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)); // https://msdn.microsoft.com/ru-ru/library/windows/desktop/5fc6ft2t(v=vs.80).aspx if(handleFile==INVALID_HANDLE_VALUE) { return; } CHandle hFile(handleFile); // Write minidump to the file mei.ThreadId = GetCurrentThreadId(); mei.ExceptionPointers = pExcPtrs; mei.ClientPointers = FALSE; mci.CallbackRoutine = NULL; mci.CallbackParam = NULL; typedef BOOL (WINAPI *LPMINIDUMPWRITEDUMP)( HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_USER_STREAM_INFORMATION UserEncoderParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam); LPMINIDUMPWRITEDUMP pfnMiniDumpWriteDump = (LPMINIDUMPWRITEDUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); if(!pfnMiniDumpWriteDump) { // Bad MiniDumpWriteDump function return; } HANDLE hProcess = GetCurrentProcess(); DWORD dwProcessId = GetCurrentProcessId(); auto dump_type = (_MINIDUMP_TYPE)get_dump_type(); if (dump_type == -1) { assert(!"dump_type must be positive"); dump_type = MiniDumpNormal; } BOOL bWriteDump = pfnMiniDumpWriteDump( hProcess, dwProcessId, hFile, dump_type, &mei, NULL, &mci); if(!bWriteDump) { // Error writing dump. return; } // Unload dbghelp.dll FreeLibrary(hDbgHelp); }
static int debuggerd_dispatch_pseudothread(void* arg) { debugger_thread_info* thread_info = static_cast<debugger_thread_info*>(arg); for (int i = 0; i < 1024; ++i) { close(i); } int devnull = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)); // devnull will be 0. TEMP_FAILURE_RETRY(dup2(devnull, STDOUT_FILENO)); TEMP_FAILURE_RETRY(dup2(devnull, STDERR_FILENO)); int pipefds[2]; if (pipe(pipefds) != 0) { fatal_errno("failed to create pipe"); } // Don't use fork(2) to avoid calling pthread_atfork handlers. int forkpid = clone(nullptr, nullptr, 0, nullptr); if (forkpid == -1) { async_safe_format_log(ANDROID_LOG_FATAL, "libc", "failed to fork in debuggerd signal handler: %s", strerror(errno)); } else if (forkpid == 0) { TEMP_FAILURE_RETRY(dup2(pipefds[1], STDOUT_FILENO)); close(pipefds[0]); close(pipefds[1]); raise_caps(); char main_tid[10]; char pseudothread_tid[10]; char debuggerd_dump_type[10]; async_safe_format_buffer(main_tid, sizeof(main_tid), "%d", thread_info->crashing_tid); async_safe_format_buffer(pseudothread_tid, sizeof(pseudothread_tid), "%d", thread_info->pseudothread_tid); async_safe_format_buffer(debuggerd_dump_type, sizeof(debuggerd_dump_type), "%d", get_dump_type(thread_info)); execl(CRASH_DUMP_PATH, CRASH_DUMP_NAME, main_tid, pseudothread_tid, debuggerd_dump_type, nullptr); fatal_errno("exec failed"); } else { close(pipefds[1]); char buf[4]; ssize_t rc = TEMP_FAILURE_RETRY(read(pipefds[0], &buf, sizeof(buf))); if (rc == -1) { async_safe_format_log(ANDROID_LOG_FATAL, "libc", "read of IPC pipe failed: %s", strerror(errno)); } else if (rc == 0) { async_safe_format_log(ANDROID_LOG_FATAL, "libc", "crash_dump helper failed to exec"); } else if (rc != 1) { async_safe_format_log(ANDROID_LOG_FATAL, "libc", "read of IPC pipe returned unexpected value: %zd", rc); } else { if (buf[0] != '\1') { async_safe_format_log(ANDROID_LOG_FATAL, "libc", "crash_dump helper reported failure"); } else { thread_info->crash_dump_started = true; } } close(pipefds[0]); // Don't leave a zombie child. int status; if (TEMP_FAILURE_RETRY(waitpid(forkpid, &status, 0)) == -1) { async_safe_format_log(ANDROID_LOG_FATAL, "libc", "failed to wait for crash_dump helper: %s", strerror(errno)); } else if (WIFSTOPPED(status) || WIFSIGNALED(status)) { async_safe_format_log(ANDROID_LOG_FATAL, "libc", "crash_dump helper crashed or stopped"); thread_info->crash_dump_started = false; } } syscall(__NR_exit, 0); return 0; }