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

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

Issue 7190019: Always search TIDs for the crashing processes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 6 months 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
« no previous file with comments | « base/linux_util.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/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/syscall.h> 10 #include <sys/syscall.h>
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 if (crashing_pid == -1 || partner_fd == -1 || signal_fd == -1) { 214 if (crashing_pid == -1 || partner_fd == -1 || signal_fd == -1) {
215 LOG(ERROR) << "Death signal message didn't contain all expected control" 215 LOG(ERROR) << "Death signal message didn't contain all expected control"
216 << " messages"; 216 << " messages";
217 if (partner_fd >= 0) 217 if (partner_fd >= 0)
218 HANDLE_EINTR(close(partner_fd)); 218 HANDLE_EINTR(close(partner_fd));
219 if (signal_fd >= 0) 219 if (signal_fd >= 0)
220 HANDLE_EINTR(close(signal_fd)); 220 HANDLE_EINTR(close(signal_fd));
221 return; 221 return;
222 } 222 }
223 223
224 // Kernel bug workaround (broken in 2.6.30 at least): 224 // Kernel bug workaround (broken in 2.6.30 and 2.6.32, working in 2.6.38).
225 // The kernel doesn't translate PIDs in SCM_CREDENTIALS across PID 225 // The kernel doesn't translate PIDs in SCM_CREDENTIALS across PID
226 // namespaces. Thus |crashing_pid| might be garbage from our point of view. 226 // namespaces. Thus |crashing_pid| might be garbage from our point of view.
227 // In the future we can remove this workaround, but we have to wait a couple 227 // In the future we can remove this workaround, but we have to wait a couple
228 // of years to be sure that it's worked its way out into the world. 228 // of years to be sure that it's worked its way out into the world.
229 // TODO(thestig) Remove the workaround when Ubuntu Lucid is deprecated.
229 230
230 // The crashing process closes its copy of the signal_fd immediately after 231 // The crashing process closes its copy of the signal_fd immediately after
231 // calling sendmsg(). We can thus not reliably look for with with 232 // calling sendmsg(). We can thus not reliably look for with with
232 // FindProcessHoldingSocket(). But by necessity, it has to keep the 233 // FindProcessHoldingSocket(). But by necessity, it has to keep the
233 // partner_fd open until the crashdump is complete. 234 // partner_fd open until the crashdump is complete.
234 uint64_t inode_number; 235 uint64_t inode_number;
235 if (!base::FileDescriptorGetInode(&inode_number, partner_fd)) { 236 if (!base::FileDescriptorGetInode(&inode_number, partner_fd)) {
236 LOG(WARNING) << "Failed to get inode number for passed socket"; 237 LOG(WARNING) << "Failed to get inode number for passed socket";
237 HANDLE_EINTR(close(partner_fd)); 238 HANDLE_EINTR(close(partner_fd));
238 HANDLE_EINTR(close(signal_fd)); 239 HANDLE_EINTR(close(signal_fd));
239 return; 240 return;
240 } 241 }
241 HANDLE_EINTR(close(partner_fd)); 242 HANDLE_EINTR(close(partner_fd));
242 243
243 pid_t actual_crashing_pid = -1; 244 pid_t actual_crashing_pid = -1;
244 if (!base::FindProcessHoldingSocket(&actual_crashing_pid, inode_number)) { 245 if (!base::FindProcessHoldingSocket(&actual_crashing_pid, inode_number)) {
245 LOG(WARNING) << "Failed to find process holding other end of crash reply " 246 LOG(WARNING) << "Failed to find process holding other end of crash reply "
246 "socket"; 247 "socket";
247 HANDLE_EINTR(close(signal_fd)); 248 HANDLE_EINTR(close(signal_fd));
248 return; 249 return;
249 } 250 }
250 251
251 if (actual_crashing_pid != crashing_pid) { 252 crashing_pid = actual_crashing_pid;
252 crashing_pid = actual_crashing_pid;
253 253
254 // The crashing TID set inside the compromised context via sys_gettid() 254 // The crashing TID set inside the compromised context via
255 // in ExceptionHandler::HandleSignal is also wrong and needs to be 255 // sys_gettid() in ExceptionHandler::HandleSignal might be wrong (if
256 // translated. 256 // the kernel supports PID namespacing) and may need to be
257 // 257 // translated.
258 // We expect the crashing thread to be in sys_read(), waiting for use to 258 //
259 // write to |signal_fd|. Most newer kernels where we have the different pid 259 // We expect the crashing thread to be in sys_read(), waiting for us to
260 // namespaces also have /proc/[pid]/syscall, so we can look through 260 // write to |signal_fd|. Most newer kernels where we have the different pid
261 // |actual_crashing_pid|'s thread group and find the thread that's in the 261 // namespaces also have /proc/[pid]/syscall, so we can look through
262 // read syscall with the right arguments. 262 // |actual_crashing_pid|'s thread group and find the thread that's in the
263 // read syscall with the right arguments.
263 264
264 std::string expected_syscall_data; 265 std::string expected_syscall_data;
265 // /proc/[pid]/syscall is formatted as follows: 266 // /proc/[pid]/syscall is formatted as follows:
266 // syscall_number arg1 ... arg6 sp pc 267 // syscall_number arg1 ... arg6 sp pc
267 // but we just check syscall_number through arg3. 268 // but we just check syscall_number through arg3.
268 base::StringAppendF(&expected_syscall_data, "%d 0x%x %p 0x1 ", 269 base::StringAppendF(&expected_syscall_data, "%d 0x%x %p 0x1 ",
269 SYS_read, tid_fd, tid_buf_addr); 270 SYS_read, tid_fd, tid_buf_addr);
270 pid_t crashing_tid = 271 bool syscall_supported = false;
271 base::FindThreadIDWithSyscall(crashing_pid, expected_syscall_data); 272 pid_t crashing_tid =
272 if (crashing_tid == -1) { 273 base::FindThreadIDWithSyscall(crashing_pid,
273 // We didn't find the thread we want. Maybe it didn't reach sys_read() 274 expected_syscall_data,
274 // yet, or the kernel doesn't support /proc/[pid]/syscall or the thread 275 &syscall_supported);
275 // went away. We'll just take a guess here and assume the crashing 276 if (crashing_tid == -1 && syscall_supported) {
276 // thread is the thread group leader. 277 // We didn't find the thread we want. Maybe it didn't reach
277 crashing_tid = crashing_pid; 278 // sys_read() yet or the thread went away. We'll just take a
278 } 279 // guess here and assume the crashing thread is the thread group
280 // leader. If procfs syscall is not supported by the kernel, then
281 // we assume the kernel also does not support TID namespacing and
282 // trust the TID passed by the crashing process.
283 crashing_tid = crashing_pid;
284 }
279 285
280 ExceptionHandler::CrashContext* bad_context = 286 ExceptionHandler::CrashContext* bad_context =
281 reinterpret_cast<ExceptionHandler::CrashContext*>(crash_context); 287 reinterpret_cast<ExceptionHandler::CrashContext*>(crash_context);
282 bad_context->tid = crashing_tid; 288 bad_context->tid = crashing_tid;
283 }
284 289
285 // Sanitize the string data a bit more 290 // Sanitize the string data a bit more
286 guid[kGuidSize] = crash_url[kMaxActiveURLSize] = distro[kDistroSize] = 0; 291 guid[kGuidSize] = crash_url[kMaxActiveURLSize] = distro[kDistroSize] = 0;
287 292
288 // Freed in CrashDumpTask(); 293 // Freed in CrashDumpTask();
289 BreakpadInfo* info = new BreakpadInfo; 294 BreakpadInfo* info = new BreakpadInfo;
290 295
291 info->process_type_length = process_type_.length(); 296 info->process_type_length = process_type_.length();
292 char* process_type_str = new char[info->process_type_length + 1]; 297 char* process_type_str = new char[info->process_type_length + 1];
293 process_type_.copy(process_type_str, info->process_type_length); 298 process_type_.copy(process_type_str, info->process_type_length);
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 } 445 }
441 446
442 void PpapiCrashHandlerHostLinux::SetProcessType() { 447 void PpapiCrashHandlerHostLinux::SetProcessType() {
443 process_type_ = "ppapi"; 448 process_type_ = "ppapi";
444 } 449 }
445 450
446 // static 451 // static
447 PpapiCrashHandlerHostLinux* PpapiCrashHandlerHostLinux::GetInstance() { 452 PpapiCrashHandlerHostLinux* PpapiCrashHandlerHostLinux::GetInstance() {
448 return Singleton<PpapiCrashHandlerHostLinux>::get(); 453 return Singleton<PpapiCrashHandlerHostLinux>::get();
449 } 454 }
OLDNEW
« no previous file with comments | « base/linux_util.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698