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