crash_generation_server.cc revision 83e085b7a331c96237cf8e814f97b3ef4c36a70f
183e085b7a331c96237cf8e814f97b3ef4c36a70fjimblandy// Copyright (c) 2010 Google Inc. 2f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// All rights reserved. 3f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// 4f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// Redistribution and use in source and binary forms, with or without 5f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// modification, are permitted provided that the following conditions are 6f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// met: 7f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// 8f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// * Redistributions of source code must retain the above copyright 9f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// notice, this list of conditions and the following disclaimer. 10f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// * Redistributions in binary form must reproduce the above 11f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// copyright notice, this list of conditions and the following disclaimer 12f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// in the documentation and/or other materials provided with the 13f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// distribution. 14f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// * Neither the name of Google Inc. nor the names of its 15f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// contributors may be used to endorse or promote products derived from 16f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// this software without specific prior written permission. 17f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// 18f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 30f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <assert.h> 31f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <dirent.h> 32f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <fcntl.h> 33f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <limits.h> 34f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <poll.h> 35f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <stdio.h> 36f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <string.h> 37f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <sys/socket.h> 38f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <sys/stat.h> 39f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <sys/types.h> 40f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include <unistd.h> 41f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 42f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include "client/linux/crash_generation/crash_generation_server.h" 43f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include "client/linux/crash_generation/client_info.h" 44f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include "client/linux/handler/exception_handler.h" 45f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include "client/linux/minidump_writer/minidump_writer.h" 46f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include "common/linux/eintr_wrapper.h" 47f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek#include "common/linux/guid_creator.h" 48f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 49f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekstatic const char kCommandQuit = 'x'; 50f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 51f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekstatic bool 52f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekGetInodeForFileDescriptor(ino_t* inode_out, int fd) 53f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 54f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(inode_out); 55f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 56f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek struct stat buf; 57f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (fstat(fd, &buf) < 0) 58f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 59f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 60f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (!S_ISSOCK(buf.st_mode)) 61f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 62f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 63f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek *inode_out = buf.st_ino; 64f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 65f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 66f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 67f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// expected prefix of the target of the /proc/self/fd/%d link for a socket 68f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekstatic const char kSocketLinkPrefix[] = "socket:["; 69f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 70f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// Parse a symlink in /proc/pid/fd/$x and return the inode number of the 71f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// socket. 72f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// inode_out: (output) set to the inode number on success 73f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// path: e.g. /proc/1234/fd/5 (must be a UNIX domain socket descriptor) 74f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekstatic bool 75f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekGetInodeForProcPath(ino_t* inode_out, const char* path) 76f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 77f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(inode_out); 78f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(path); 79f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 80f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char buf[256]; 81f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const ssize_t n = readlink(path, buf, sizeof(buf) - 1); 82f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (n == -1) { 83f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 84f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 85f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek buf[n] = 0; 86f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 87f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (0 != memcmp(kSocketLinkPrefix, buf, sizeof(kSocketLinkPrefix) - 1)) { 88f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 89f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 90f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 91f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char* endptr; 92f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const u_int64_t inode_ul = 93f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek strtoull(buf + sizeof(kSocketLinkPrefix) - 1, &endptr, 10); 94f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (*endptr != ']') 95f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 96f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 97f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (inode_ul == ULLONG_MAX) { 98f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 99f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 100f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 101f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek *inode_out = inode_ul; 102f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 103f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 104f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 105f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekstatic bool 106f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekFindProcessHoldingSocket(pid_t* pid_out, ino_t socket_inode) 107f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 108f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(pid_out); 109f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek bool already_found = false; 110f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 111f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek DIR* proc = opendir("/proc"); 112f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (!proc) { 113f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 114f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 115f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 116f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek std::vector<pid_t> pids; 117f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 118f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek struct dirent* dent; 119f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek while ((dent = readdir(proc))) { 120f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char* endptr; 121f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const unsigned long int pid_ul = strtoul(dent->d_name, &endptr, 10); 122f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (pid_ul == ULONG_MAX || '\0' != *endptr) 123f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek continue; 124f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek pids.push_back(pid_ul); 125f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 126f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek closedir(proc); 127f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 128f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek for (std::vector<pid_t>::const_iterator 129f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek i = pids.begin(); i != pids.end(); ++i) { 130f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const pid_t current_pid = *i; 131f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char buf[256]; 132f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek snprintf(buf, sizeof(buf), "/proc/%d/fd", current_pid); 133f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek DIR* fd = opendir(buf); 134f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (!fd) 135f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek continue; 136f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 137f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek while ((dent = readdir(fd))) { 138f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (snprintf(buf, sizeof(buf), "/proc/%d/fd/%s", current_pid, 139f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek dent->d_name) >= static_cast<int>(sizeof(buf))) { 140f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek continue; 141f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 142f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 143f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek ino_t fd_inode; 144f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (GetInodeForProcPath(&fd_inode, buf) 145f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek && fd_inode == socket_inode) { 146f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (already_found) { 147f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek closedir(fd); 148f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 149f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 150f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 151f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek already_found = true; 152f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek *pid_out = current_pid; 153f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek break; 154f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 155f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 156f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 157f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek closedir(fd); 158f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 159f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 160f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return already_found; 161f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 162f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 163f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczareknamespace google_breakpad { 164f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 165f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::CrashGenerationServer( 166f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const int listen_fd, 167f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek OnClientDumpRequestCallback dump_callback, 168f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek void* dump_context, 169f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek OnClientExitingCallback exit_callback, 170f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek void* exit_context, 171f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek bool generate_dumps, 172f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const std::string* dump_path) : 173f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek server_fd_(listen_fd), 174f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek dump_callback_(dump_callback), 175f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek dump_context_(dump_context), 176f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek exit_callback_(exit_callback), 177f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek exit_context_(exit_context), 178f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek generate_dumps_(generate_dumps), 179f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek started_(false) 180f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 181f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (dump_path) 182f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek dump_dir_ = *dump_path; 183f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek else 184f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek dump_dir_ = "/tmp"; 185f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 186f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 187f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::~CrashGenerationServer() 188f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 189f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (started_) 190f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek Stop(); 191f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 192f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 193f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekbool 194f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::Start() 195f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 196f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (started_ || 0 > server_fd_) 197f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 198f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 199f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek int control_pipe[2]; 200f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (pipe(control_pipe)) 201f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 202f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 203f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (fcntl(control_pipe[0], F_SETFD, FD_CLOEXEC)) 204f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 205f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (fcntl(control_pipe[1], F_SETFD, FD_CLOEXEC)) 206f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 207f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 208f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (fcntl(control_pipe[0], F_SETFL, O_NONBLOCK)) 209f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 210f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 211f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek control_pipe_in_ = control_pipe[0]; 212f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek control_pipe_out_ = control_pipe[1]; 213f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 214f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (pthread_create(&thread_, NULL, 215f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek ThreadMain, reinterpret_cast<void*>(this))) 216f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 217f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 218f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek started_ = true; 219f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 220f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 221f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 222f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekvoid 223f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::Stop() 224f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 225f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(pthread_self() != thread_); 226f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 227f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (!started_) 228f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return; 229f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 230f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek HANDLE_EINTR(write(control_pipe_out_, &kCommandQuit, 1)); 231f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 232f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek void* dummy; 233f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek pthread_join(thread_, &dummy); 234f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 235f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek started_ = false; 236f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 237f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 238f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek//static 239f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekbool 240f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::CreateReportChannel(int* server_fd, int* client_fd) 241f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 242f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek int fds[2]; 243f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 244f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds)) 245f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 246f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 247f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek static const int on = 1; 248f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // Enable passcred on the server end of the socket 249f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (setsockopt(fds[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) 250f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 251f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 252f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (fcntl(fds[1], F_SETFL, O_NONBLOCK)) 253f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 254f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (fcntl(fds[1], F_SETFD, FD_CLOEXEC)) 255f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 256f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 257f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek *client_fd = fds[0]; 258f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek *server_fd = fds[1]; 259f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 260f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 261f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 262f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// The following methods/functions execute on the server thread 263f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 264f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekvoid 265f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::Run() 266f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 267f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek struct pollfd pollfds[2]; 268f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek memset(&pollfds, 0, sizeof(pollfds)); 269f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 270f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek pollfds[0].fd = server_fd_; 271f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek pollfds[0].events = POLLIN; 272f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 273f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek pollfds[1].fd = control_pipe_in_; 274f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek pollfds[1].events = POLLIN; 275f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 276f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek while (true) { 277f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // infinite timeout 278f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek int nevents = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), -1); 279f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (-1 == nevents) { 280f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (EINTR == errno) { 281f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek continue; 282f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } else { 283f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return; 284f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 285f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 286f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 287f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (pollfds[0].revents && !ClientEvent(pollfds[0].revents)) 288f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return; 289f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 290f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (pollfds[1].revents && !ControlEvent(pollfds[1].revents)) 291f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return; 292f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 293f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 294f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 295f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekbool 296f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::ClientEvent(short revents) 297f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 298f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (POLLHUP & revents) 299f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 300f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(POLLIN & revents); 301f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 302f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // A process has crashed and has signaled us by writing a datagram 303f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // to the death signal socket. The datagram contains the crash context needed 304f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // for writing the minidump as well as a file descriptor and a credentials 305f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // block so that they can't lie about their pid. 306f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 307f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // The length of the control message: 308f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek static const unsigned kControlMsgSize = 309f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred)); 310f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // The length of the regular payload: 311f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek static const unsigned kCrashContextSize = 312f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek sizeof(google_breakpad::ExceptionHandler::CrashContext); 313f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 314f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek struct msghdr msg = {0}; 315f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek struct iovec iov[1]; 316f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char crash_context[kCrashContextSize]; 317f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char control[kControlMsgSize]; 318f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const ssize_t expected_msg_size = sizeof(crash_context); 319f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 320f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek iov[0].iov_base = crash_context; 321f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek iov[0].iov_len = sizeof(crash_context); 322f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek msg.msg_iov = iov; 323f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek msg.msg_iovlen = sizeof(iov)/sizeof(iov[0]); 324f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek msg.msg_control = control; 325f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek msg.msg_controllen = kControlMsgSize; 326f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 327f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const ssize_t msg_size = HANDLE_EINTR(recvmsg(server_fd_, &msg, 0)); 328f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (msg_size != expected_msg_size) 329f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 330f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 331f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (msg.msg_controllen != kControlMsgSize || 332f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek msg.msg_flags & ~MSG_TRUNC) 333f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 334f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 335f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // Walk the control payload and extract the file descriptor and validated pid. 336f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek pid_t crashing_pid = -1; 337f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek int signal_fd = -1; 338f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr; 339f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek hdr = CMSG_NXTHDR(&msg, hdr)) { 340f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (hdr->cmsg_level != SOL_SOCKET) 341f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek continue; 342f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (hdr->cmsg_type == SCM_RIGHTS) { 343f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const unsigned len = hdr->cmsg_len - 344f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr); 345f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(len % sizeof(int) == 0u); 346f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const unsigned num_fds = len / sizeof(int); 347f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (num_fds > 1 || num_fds == 0) { 348f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // A nasty process could try and send us too many descriptors and 349f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // force a leak. 350f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek for (unsigned i = 0; i < num_fds; ++i) 351f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek HANDLE_EINTR(close(reinterpret_cast<int*>(CMSG_DATA(hdr))[i])); 352f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 353f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } else { 354f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek signal_fd = reinterpret_cast<int*>(CMSG_DATA(hdr))[0]; 355f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 356f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } else if (hdr->cmsg_type == SCM_CREDENTIALS) { 357f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek const struct ucred *cred = 358f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek reinterpret_cast<struct ucred*>(CMSG_DATA(hdr)); 359f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek crashing_pid = cred->pid; 360f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 361f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 362f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 363f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (crashing_pid == -1 || signal_fd == -1) { 364f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (signal_fd) 365f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek HANDLE_EINTR(close(signal_fd)); 366f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 367f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 368f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 369f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // Kernel bug workaround (broken in 2.6.30 at least): 370f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // The kernel doesn't translate PIDs in SCM_CREDENTIALS across PID 371f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // namespaces. Thus |crashing_pid| might be garbage from our point of view. 372f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // In the future we can remove this workaround, but we have to wait a couple 373f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // of years to be sure that it's worked its way out into the world. 374f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 375f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek ino_t inode_number; 376f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (!GetInodeForFileDescriptor(&inode_number, signal_fd)) { 377f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek HANDLE_EINTR(close(signal_fd)); 378f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 379f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 380f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 381f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (!FindProcessHoldingSocket(&crashing_pid, inode_number - 1)) { 382f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek HANDLE_EINTR(close(signal_fd)); 383f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 384f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 385f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 386f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek std::string minidump_filename; 387f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (!MakeMinidumpFilename(minidump_filename)) 388f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 389f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 390f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (!google_breakpad::WriteMinidump(minidump_filename.c_str(), 391f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek crashing_pid, crash_context, 392f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek kCrashContextSize)) { 393f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek HANDLE_EINTR(close(signal_fd)); 394f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 395f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 396f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 397f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (dump_callback_) { 398f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek ClientInfo info; 399f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 400f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek info.crash_server_ = this; 401f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek info.pid_ = crashing_pid; 402f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 403f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek dump_callback_(dump_context_, &info, &minidump_filename); 404f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 405f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 406f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek // Send the done signal to the process: it can exit now. 407f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek memset(&msg, 0, sizeof(msg)); 408f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek struct iovec done_iov; 409f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek done_iov.iov_base = const_cast<char*>("\x42"); 410f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek done_iov.iov_len = 1; 411f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek msg.msg_iov = &done_iov; 412f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek msg.msg_iovlen = 1; 413f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 414f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek HANDLE_EINTR(sendmsg(signal_fd, &msg, MSG_DONTWAIT | MSG_NOSIGNAL)); 415f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek HANDLE_EINTR(close(signal_fd)); 416f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 417f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 418f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 419f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 420f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekbool 421f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::ControlEvent(short revents) 422f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 423f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (POLLHUP & revents) 424f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 425f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(POLLIN & revents); 426f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 427f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char command; 428f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (read(control_pipe_in_, &command, 1)) 429f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 430f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 431f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek switch (command) { 432f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek case kCommandQuit: 433f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 434f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek default: 435f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek assert(0); 436f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek } 437f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 438f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 439f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 440f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 441f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekbool 442f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::MakeMinidumpFilename(std::string& outFilename) 443f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 444f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek GUID guid; 445f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char guidString[kGUIDStringLength+1]; 446f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 447f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek if (!(CreateGUID(&guid) 448f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek && GUIDToString(&guid, guidString, sizeof(guidString)))) 449f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return false; 450f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 451f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek char path[PATH_MAX]; 452f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek snprintf(path, sizeof(path), "%s/%s.dmp", dump_dir_.c_str(), guidString); 453f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 454f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek outFilename = path; 455f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return true; 456f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 457f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 458f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek// static 459f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekvoid* 460f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarekCrashGenerationServer::ThreadMain(void *arg) 461f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek{ 462f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek reinterpret_cast<CrashGenerationServer*>(arg)->Run(); 463f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek return NULL; 464f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} 465f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek 466f480ba116971a56d4de25ae1df2369e3d5503d16ted.mielczarek} // namespace google_breakpad 467