Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(422)

Side by Side Diff: chrome/browser/crash_handler_host_linux.cc

Issue 371015: Linux: Catch plugin crashes. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:mergeinfo
Merged /branches/chrome_webkit_merge_branch/chrome/browser/renderer_host/render_crash_handler_host_linux.cc:r69-2775
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/renderer_host/render_crash_handler_host_linux.h" 5 #include "chrome/browser/crash_handler_host_linux.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <stdlib.h> 8 #include <stdlib.h>
9 #include <sys/socket.h> 9 #include <sys/socket.h>
10 #include <sys/types.h> 10 #include <sys/types.h>
11 #include <unistd.h> 11 #include <unistd.h>
12 12
13 #include <string>
14 #include <vector>
15
16 #include "base/eintr_wrapper.h" 13 #include "base/eintr_wrapper.h"
17 #include "base/file_path.h" 14 #include "base/file_path.h"
18 #include "base/format_macros.h" 15 #include "base/format_macros.h"
19 #include "base/linux_util.h" 16 #include "base/linux_util.h"
20 #include "base/logging.h" 17 #include "base/logging.h"
21 #include "base/message_loop.h" 18 #include "base/message_loop.h"
22 #include "base/path_service.h" 19 #include "base/path_service.h"
23 #include "base/rand_util.h" 20 #include "base/rand_util.h"
24 #include "base/string_util.h" 21 #include "base/string_util.h"
25 #include "breakpad/linux/exception_handler.h" 22 #include "breakpad/linux/exception_handler.h"
26 #include "breakpad/linux/linux_dumper.h" 23 #include "breakpad/linux/linux_dumper.h"
27 #include "breakpad/linux/minidump_writer.h" 24 #include "breakpad/linux/minidump_writer.h"
28 #include "chrome/app/breakpad_linux.h" 25 #include "chrome/app/breakpad_linux.h"
29 #include "chrome/browser/chrome_thread.h" 26 #include "chrome/browser/chrome_thread.h"
30 #include "chrome/common/chrome_paths.h" 27 #include "chrome/common/chrome_paths.h"
31 28
32 // Since RenderCrashHandlerHostLinux is a singleton, it's only destroyed at the 29 // Since classes derived from CrashHandlerHostLinux are singletons, it's only
33 // end of the processes lifetime, which is greater in span then the lifetime of 30 // destroyed at the end of the processes lifetime, which is greater in span than
34 // the IO message loop. 31 // the lifetime of the IO message loop.
35 template<> struct RunnableMethodTraits<RenderCrashHandlerHostLinux> { 32 template<> struct RunnableMethodTraits<CrashHandlerHostLinux> {
36 void RetainCallee(RenderCrashHandlerHostLinux*) { } 33 void RetainCallee(CrashHandlerHostLinux*) { }
37 void ReleaseCallee(RenderCrashHandlerHostLinux*) { } 34 void ReleaseCallee(CrashHandlerHostLinux*) { }
38 }; 35 };
39 36
40 RenderCrashHandlerHostLinux::RenderCrashHandlerHostLinux() 37 CrashHandlerHostLinux::CrashHandlerHostLinux()
41 : renderer_socket_(-1), 38 : process_socket_(-1),
42 browser_socket_(-1) { 39 browser_socket_(-1) {
43 int fds[2]; 40 int fds[2];
44 // We use SOCK_SEQPACKET rather than SOCK_DGRAM to prevent the renderer from 41 // We use SOCK_SEQPACKET rather than SOCK_DGRAM to prevent the process from
45 // sending datagrams to other sockets on the system. The sandbox may prevent 42 // sending datagrams to other sockets on the system. The sandbox may prevent
46 // the renderer from calling socket() to create new sockets, but it'll still 43 // the process from calling socket() to create new sockets, but it'll still
47 // inherit some sockets. With PF_UNIX+SOCK_DGRAM, it can call sendmsg to send 44 // inherit some sockets. With PF_UNIX+SOCK_DGRAM, it can call sendmsg to send
48 // a datagram to any (abstract) socket on the same system. With 45 // a datagram to any (abstract) socket on the same system. With
49 // SOCK_SEQPACKET, this is prevented. 46 // SOCK_SEQPACKET, this is prevented.
50 CHECK(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds) == 0); 47 CHECK(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds) == 0);
51 static const int on = 1; 48 static const int on = 1;
52 49
53 // Enable passcred on the server end of the socket 50 // Enable passcred on the server end of the socket
54 CHECK(setsockopt(fds[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) == 0); 51 CHECK(setsockopt(fds[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) == 0);
55 52
56 renderer_socket_ = fds[0]; 53 process_socket_ = fds[0];
57 browser_socket_ = fds[1]; 54 browser_socket_ = fds[1];
58 55
59 ChromeThread::PostTask( 56 ChromeThread::PostTask(
60 ChromeThread::IO, FROM_HERE, 57 ChromeThread::IO, FROM_HERE,
61 NewRunnableMethod(this, &RenderCrashHandlerHostLinux::Init)); 58 NewRunnableMethod(this, &CrashHandlerHostLinux::Init));
62 } 59 }
63 60
64 RenderCrashHandlerHostLinux::~RenderCrashHandlerHostLinux() { 61 CrashHandlerHostLinux::~CrashHandlerHostLinux() {
65 HANDLE_EINTR(close(renderer_socket_)); 62 HANDLE_EINTR(close(process_socket_));
66 HANDLE_EINTR(close(browser_socket_)); 63 HANDLE_EINTR(close(browser_socket_));
67 } 64 }
68 65
69 void RenderCrashHandlerHostLinux::Init() { 66 void CrashHandlerHostLinux::Init() {
70 MessageLoopForIO* ml = MessageLoopForIO::current(); 67 MessageLoopForIO* ml = MessageLoopForIO::current();
71 CHECK(ml->WatchFileDescriptor( 68 CHECK(ml->WatchFileDescriptor(
72 browser_socket_, true /* persistent */, 69 browser_socket_, true /* persistent */,
73 MessageLoopForIO::WATCH_READ, 70 MessageLoopForIO::WATCH_READ,
74 &file_descriptor_watcher_, this)); 71 &file_descriptor_watcher_, this));
75 ml->AddDestructionObserver(this); 72 ml->AddDestructionObserver(this);
76 } 73 }
77 74
78 void RenderCrashHandlerHostLinux::OnFileCanWriteWithoutBlocking(int fd) { 75 void CrashHandlerHostLinux::OnFileCanWriteWithoutBlocking(int fd) {
79 DCHECK(false); 76 DCHECK(false);
80 } 77 }
81 78
82 void RenderCrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) { 79 void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) {
83 DCHECK_EQ(fd, browser_socket_); 80 DCHECK_EQ(fd, browser_socket_);
84 81
85 // A renderer process has crashed and has signaled us by writing a datagram 82 // A process has crashed and has signaled us by writing a datagram
86 // to the death signal socket. The datagram contains the crash context needed 83 // to the death signal socket. The datagram contains the crash context needed
87 // for writing the minidump as well as a file descriptor and a credentials 84 // for writing the minidump as well as a file descriptor and a credentials
88 // block so that they can't lie about their pid. 85 // block so that they can't lie about their pid.
89 86
90 // The length of the control message: 87 // The length of the control message:
91 static const unsigned kControlMsgSize = 88 static const unsigned kControlMsgSize =
92 CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred)); 89 CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred));
93 // The length of the regular payload: 90 // The length of the regular payload:
94 static const unsigned kCrashContextSize = 91 static const unsigned kCrashContextSize =
95 sizeof(google_breakpad::ExceptionHandler::CrashContext); 92 sizeof(google_breakpad::ExceptionHandler::CrashContext);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr; 140 for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr;
144 hdr = CMSG_NXTHDR(&msg, hdr)) { 141 hdr = CMSG_NXTHDR(&msg, hdr)) {
145 if (hdr->cmsg_level != SOL_SOCKET) 142 if (hdr->cmsg_level != SOL_SOCKET)
146 continue; 143 continue;
147 if (hdr->cmsg_type == SCM_RIGHTS) { 144 if (hdr->cmsg_type == SCM_RIGHTS) {
148 const unsigned len = hdr->cmsg_len - 145 const unsigned len = hdr->cmsg_len -
149 (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr); 146 (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr);
150 DCHECK_EQ(len % sizeof(int), 0u); 147 DCHECK_EQ(len % sizeof(int), 0u);
151 const unsigned num_fds = len / sizeof(int); 148 const unsigned num_fds = len / sizeof(int);
152 if (num_fds > 1 || num_fds == 0) { 149 if (num_fds > 1 || num_fds == 0) {
153 // A nasty renderer could try and send us too many descriptors and 150 // A nasty process could try and send us too many descriptors and
154 // force a leak. 151 // force a leak.
155 LOG(ERROR) << "Death signal contained too many descriptors;" 152 LOG(ERROR) << "Death signal contained too many descriptors;"
156 << " num_fds:" << num_fds; 153 << " num_fds:" << num_fds;
157 for (unsigned i = 0; i < num_fds; ++i) 154 for (unsigned i = 0; i < num_fds; ++i)
158 HANDLE_EINTR(close(reinterpret_cast<int*>(CMSG_DATA(hdr))[i])); 155 HANDLE_EINTR(close(reinterpret_cast<int*>(CMSG_DATA(hdr))[i]));
159 return; 156 return;
160 } else { 157 } else {
161 signal_fd = reinterpret_cast<int*>(CMSG_DATA(hdr))[0]; 158 signal_fd = reinterpret_cast<int*>(CMSG_DATA(hdr))[0];
162 } 159 }
163 } else if (hdr->cmsg_type == SCM_CREDENTIALS) { 160 } else if (hdr->cmsg_type == SCM_CREDENTIALS) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 } 193 }
197 194
198 bool upload = true; 195 bool upload = true;
199 FilePath dumps_path("/tmp"); 196 FilePath dumps_path("/tmp");
200 if (getenv("CHROME_HEADLESS")) { 197 if (getenv("CHROME_HEADLESS")) {
201 upload = false; 198 upload = false;
202 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path); 199 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
203 } 200 }
204 const uint64 rand = base::RandUint64(); 201 const uint64 rand = base::RandUint64();
205 const std::string minidump_filename = 202 const std::string minidump_filename =
206 StringPrintf("%s/chromium-renderer-minidump-%016" PRIx64 ".dmp", 203 StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".dmp",
207 dumps_path.value().c_str(), rand); 204 dumps_path.value().c_str(), process_type_.c_str(), rand);
208 if (!google_breakpad::WriteMinidump(minidump_filename.c_str(), 205 if (!google_breakpad::WriteMinidump(minidump_filename.c_str(),
209 crashing_pid, crash_context, 206 crashing_pid, crash_context,
210 kCrashContextSize)) { 207 kCrashContextSize)) {
211 LOG(ERROR) << "Failed to write crash dump for pid " << crashing_pid; 208 LOG(ERROR) << "Failed to write crash dump for pid " << crashing_pid;
212 HANDLE_EINTR(close(signal_fd)); 209 HANDLE_EINTR(close(signal_fd));
213 } 210 }
214 211
215 // Send the done signal to the renderer: it can exit now. 212 // Send the done signal to the process: it can exit now.
216 memset(&msg, 0, sizeof(msg)); 213 memset(&msg, 0, sizeof(msg));
217 struct iovec done_iov; 214 struct iovec done_iov;
218 done_iov.iov_base = const_cast<char*>("\x42"); 215 done_iov.iov_base = const_cast<char*>("\x42");
219 done_iov.iov_len = 1; 216 done_iov.iov_len = 1;
220 msg.msg_iov = &done_iov; 217 msg.msg_iov = &done_iov;
221 msg.msg_iovlen = 1; 218 msg.msg_iovlen = 1;
222 219
223 HANDLE_EINTR(sendmsg(signal_fd, &msg, MSG_DONTWAIT | MSG_NOSIGNAL)); 220 HANDLE_EINTR(sendmsg(signal_fd, &msg, MSG_DONTWAIT | MSG_NOSIGNAL));
224 HANDLE_EINTR(close(signal_fd)); 221 HANDLE_EINTR(close(signal_fd));
225 222
226 // Sanitize the string data a bit more 223 // Sanitize the string data a bit more
227 guid[kGuidSize] = crash_url[kMaxActiveURLSize] = distro[kDistroSize] = 0; 224 guid[kGuidSize] = crash_url[kMaxActiveURLSize] = distro[kDistroSize] = 0;
228 225
229 BreakpadInfo info; 226 BreakpadInfo info;
230 info.filename = minidump_filename.c_str(); 227 info.filename = minidump_filename.c_str();
231 info.process_type = "renderer"; 228 info.process_type = process_type_.c_str();
232 info.process_type_length = 8; 229 info.process_type_length = process_type_.length();
233 info.crash_url = crash_url; 230 info.crash_url = crash_url;
234 info.crash_url_length = strlen(crash_url); 231 info.crash_url_length = strlen(crash_url);
235 info.guid = guid; 232 info.guid = guid;
236 info.guid_length = strlen(guid); 233 info.guid_length = strlen(guid);
237 info.distro = distro; 234 info.distro = distro;
238 info.distro_length = strlen(distro); 235 info.distro_length = strlen(distro);
239 info.upload = upload; 236 info.upload = upload;
240 HandleCrashDump(info); 237 HandleCrashDump(info);
241 } 238 }
242 239
243 void RenderCrashHandlerHostLinux::WillDestroyCurrentMessageLoop() { 240 void CrashHandlerHostLinux::WillDestroyCurrentMessageLoop() {
244 file_descriptor_watcher_.StopWatchingFileDescriptor(); 241 file_descriptor_watcher_.StopWatchingFileDescriptor();
245 } 242 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698