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

Side by Side Diff: src/client/linux/handler/exception_handler.cc

Issue 1354923002: Linux ExceptionHandler: don't allocate the CrashContext on the stack (Closed) Base URL: https://chromium.googlesource.com/breakpad/breakpad.git@master
Patch Set: Created 5 years, 3 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
« no previous file with comments | « no previous file | 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) 2010 Google Inc. 1 // Copyright (c) 2010 Google Inc.
2 // All rights reserved. 2 // All rights reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // * Redistributions of source code must retain the above copyright 8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer. 9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above 10 // * Redistributions in binary form must reproduce the above
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 signal(sig, SIG_DFL); 205 signal(sig, SIG_DFL);
206 #endif 206 #endif
207 } 207 }
208 208
209 // The global exception handler stack. This is needed because there may exist 209 // The global exception handler stack. This is needed because there may exist
210 // multiple ExceptionHandler instances in a process. Each will have itself 210 // multiple ExceptionHandler instances in a process. Each will have itself
211 // registered in this stack. 211 // registered in this stack.
212 std::vector<ExceptionHandler*>* g_handler_stack_ = NULL; 212 std::vector<ExceptionHandler*>* g_handler_stack_ = NULL;
213 pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER; 213 pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER;
214 214
215 // sizeof(CrashContext) can be too big w.r.t the size of alternatate stack
216 // for SignalHandler(). Keep the crash context as a .bss field. Exception
217 // handlers are serialized by the |g_handler_stack_mutex_| and at most one at a
218 // time can use |g_crash_context_|.
219 ExceptionHandler::CrashContext g_crash_context_;
220
215 } // namespace 221 } // namespace
216 222
217 // Runs before crashing: normal context. 223 // Runs before crashing: normal context.
218 ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor, 224 ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor,
219 FilterCallback filter, 225 FilterCallback filter,
220 MinidumpCallback callback, 226 MinidumpCallback callback,
221 void* callback_context, 227 void* callback_context,
222 bool install_handler, 228 bool install_handler,
223 const int server_fd) 229 const int server_fd)
224 : filter_(filter), 230 : filter_(filter),
225 callback_(callback), 231 callback_(callback),
226 callback_context_(callback_context), 232 callback_context_(callback_context),
227 minidump_descriptor_(descriptor), 233 minidump_descriptor_(descriptor),
228 crash_handler_(NULL) { 234 crash_handler_(NULL) {
229 if (server_fd >= 0) 235 if (server_fd >= 0)
230 crash_generation_client_.reset(CrashGenerationClient::TryCreate(server_fd)); 236 crash_generation_client_.reset(CrashGenerationClient::TryCreate(server_fd));
231 237
232 if (!IsOutOfProcess() && !minidump_descriptor_.IsFD() && 238 if (!IsOutOfProcess() && !minidump_descriptor_.IsFD() &&
233 !minidump_descriptor_.IsMicrodumpOnConsole()) 239 !minidump_descriptor_.IsMicrodumpOnConsole())
234 minidump_descriptor_.UpdatePath(); 240 minidump_descriptor_.UpdatePath();
235 241
236 #if defined(__ANDROID__) 242 #if defined(__ANDROID__)
237 if (minidump_descriptor_.IsMicrodumpOnConsole()) 243 if (minidump_descriptor_.IsMicrodumpOnConsole())
238 logger::initializeCrashLogWriter(); 244 logger::initializeCrashLogWriter();
239 #endif 245 #endif
240 246
241 pthread_mutex_lock(&g_handler_stack_mutex_); 247 pthread_mutex_lock(&g_handler_stack_mutex_);
248
249 // Pre-fault the crash context struct. This is to avoid failing due to OOM
Mark Mentovai 2015/09/18 22:13:20 Smart.
250 // if handling an exception when the process ran out of virtual memory.
251 memset(&g_crash_context_, 0, sizeof(g_crash_context_));
252
242 if (!g_handler_stack_) 253 if (!g_handler_stack_)
243 g_handler_stack_ = new std::vector<ExceptionHandler*>; 254 g_handler_stack_ = new std::vector<ExceptionHandler*>;
244 if (install_handler) { 255 if (install_handler) {
245 InstallAlternateStackLocked(); 256 InstallAlternateStackLocked();
246 InstallHandlersLocked(); 257 InstallHandlersLocked();
247 } 258 }
248 g_handler_stack_->push_back(this); 259 g_handler_stack_->push_back(this);
249 pthread_mutex_unlock(&g_handler_stack_mutex_); 260 pthread_mutex_unlock(&g_handler_stack_mutex_);
250 } 261 }
251 262
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 if (filter_ && !filter_(callback_context_)) 428 if (filter_ && !filter_(callback_context_))
418 return false; 429 return false;
419 430
420 // Allow ourselves to be dumped if the signal is trusted. 431 // Allow ourselves to be dumped if the signal is trusted.
421 bool signal_trusted = info->si_code > 0; 432 bool signal_trusted = info->si_code > 0;
422 bool signal_pid_trusted = info->si_code == SI_USER || 433 bool signal_pid_trusted = info->si_code == SI_USER ||
423 info->si_code == SI_TKILL; 434 info->si_code == SI_TKILL;
424 if (signal_trusted || (signal_pid_trusted && info->si_pid == getpid())) { 435 if (signal_trusted || (signal_pid_trusted && info->si_pid == getpid())) {
425 sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); 436 sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
426 } 437 }
427 CrashContext context; 438
428 // Fill in all the holes in the struct to make Valgrind happy. 439 // Fill in all the holes in the struct to make Valgrind happy.
429 memset(&context, 0, sizeof(context)); 440 memset(&g_crash_context_, 0, sizeof(g_crash_context_));
Mark Mentovai 2015/09/18 22:13:20 Necessary? You already wrote zeroes into it when y
Primiano Tucci (use gerrit) 2015/09/18 22:22:40 Right, should be safe from the production code any
Mark Mentovai 2015/09/18 22:34:56 Primiano Tucci wrote:
430 memcpy(&context.siginfo, info, sizeof(siginfo_t)); 441 memcpy(&g_crash_context_.siginfo, info, sizeof(siginfo_t));
431 memcpy(&context.context, uc, sizeof(struct ucontext)); 442 memcpy(&g_crash_context_.context, uc, sizeof(struct ucontext));
432 #if defined(__aarch64__) 443 #if defined(__aarch64__)
433 struct ucontext *uc_ptr = (struct ucontext*)uc; 444 struct ucontext* uc_ptr = (struct ucontext*)uc;
434 struct fpsimd_context *fp_ptr = 445 struct fpsimd_context* fp_ptr =
435 (struct fpsimd_context*)&uc_ptr->uc_mcontext.__reserved; 446 (struct fpsimd_context*)&uc_ptr->uc_mcontext.__reserved;
436 if (fp_ptr->head.magic == FPSIMD_MAGIC) { 447 if (fp_ptr->head.magic == FPSIMD_MAGIC) {
437 memcpy(&context.float_state, fp_ptr, sizeof(context.float_state)); 448 memcpy(&g_crash_context_.float_state, fp_ptr,
449 sizeof(g_crash_context_.float_state));
438 } 450 }
439 #elif !defined(__ARM_EABI__) && !defined(__mips__) 451 #elif !defined(__ARM_EABI__) && !defined(__mips__)
440 // FP state is not part of user ABI on ARM Linux. 452 // FP state is not part of user ABI on ARM Linux.
441 // In case of MIPS Linux FP state is already part of struct ucontext 453 // In case of MIPS Linux FP state is already part of struct ucontext
442 // and 'float_state' is not a member of CrashContext. 454 // and 'float_state' is not a member of CrashContext.
443 struct ucontext *uc_ptr = (struct ucontext*)uc; 455 struct ucontext* uc_ptr = (struct ucontext*)uc;
444 if (uc_ptr->uc_mcontext.fpregs) { 456 if (uc_ptr->uc_mcontext.fpregs) {
445 memcpy(&context.float_state, 457 memcpy(&g_crash_context_.float_state, uc_ptr->uc_mcontext.fpregs,
446 uc_ptr->uc_mcontext.fpregs, 458 sizeof(g_crash_context_.float_state));
447 sizeof(context.float_state));
448 } 459 }
449 #endif 460 #endif
450 context.tid = syscall(__NR_gettid); 461 g_crash_context_.tid = syscall(__NR_gettid);
451 if (crash_handler_ != NULL) { 462 if (crash_handler_ != NULL) {
452 if (crash_handler_(&context, sizeof(context), callback_context_)) { 463 if (crash_handler_(&g_crash_context_, sizeof(g_crash_context_),
464 callback_context_)) {
453 return true; 465 return true;
454 } 466 }
455 } 467 }
456 return GenerateDump(&context); 468 return GenerateDump(&g_crash_context_);
457 } 469 }
458 470
459 // This is a public interface to HandleSignal that allows the client to 471 // This is a public interface to HandleSignal that allows the client to
460 // generate a crash dump. This function may run in a compromised context. 472 // generate a crash dump. This function may run in a compromised context.
461 bool ExceptionHandler::SimulateSignalDelivery(int sig) { 473 bool ExceptionHandler::SimulateSignalDelivery(int sig) {
462 siginfo_t siginfo = {}; 474 siginfo_t siginfo = {};
463 // Mimic a trusted signal to allow tracing the process (see 475 // Mimic a trusted signal to allow tracing the process (see
464 // ExceptionHandler::HandleSignal(). 476 // ExceptionHandler::HandleSignal().
465 siginfo.si_code = SI_USER; 477 siginfo.si_code = SI_USER;
466 siginfo.si_pid = getpid(); 478 siginfo.si_pid = getpid();
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 descriptor.UpdatePath(); 757 descriptor.UpdatePath();
746 if (!google_breakpad::WriteMinidump(descriptor.path(), 758 if (!google_breakpad::WriteMinidump(descriptor.path(),
747 child, 759 child,
748 child_blamed_thread)) 760 child_blamed_thread))
749 return false; 761 return false;
750 762
751 return callback ? callback(descriptor, callback_context, true) : true; 763 return callback ? callback(descriptor, callback_context, true) : true;
752 } 764 }
753 765
754 } // namespace google_breakpad 766 } // namespace google_breakpad
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698