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