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