Index: src/client/linux/handler/exception_handler.cc |
diff --git a/src/client/linux/handler/exception_handler.cc b/src/client/linux/handler/exception_handler.cc |
index 9b20fe25195fde766403c7ca7cc41b880252a0d9..5bd2d8ccc6aed4693fca8aa746c7779775d6dc51 100644 |
--- a/src/client/linux/handler/exception_handler.cc |
+++ b/src/client/linux/handler/exception_handler.cc |
@@ -212,6 +212,12 @@ void InstallDefaultHandler(int sig) { |
std::vector<ExceptionHandler*>* g_handler_stack_ = NULL; |
pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER; |
+// sizeof(CrashContext) can be too big w.r.t the size of alternatate stack |
+// for SignalHandler(). Keep the crash context as a .bss field. Exception |
+// handlers are serialized by the |g_handler_stack_mutex_| and at most one at a |
+// time can use |g_crash_context_|. |
+ExceptionHandler::CrashContext g_crash_context_; |
+ |
} // namespace |
// Runs before crashing: normal context. |
@@ -239,6 +245,11 @@ ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor, |
#endif |
pthread_mutex_lock(&g_handler_stack_mutex_); |
+ |
+ // Pre-fault the crash context struct. This is to avoid failing due to OOM |
Mark Mentovai
2015/09/18 22:13:20
Smart.
|
+ // if handling an exception when the process ran out of virtual memory. |
+ memset(&g_crash_context_, 0, sizeof(g_crash_context_)); |
+ |
if (!g_handler_stack_) |
g_handler_stack_ = new std::vector<ExceptionHandler*>; |
if (install_handler) { |
@@ -424,36 +435,37 @@ bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) { |
if (signal_trusted || (signal_pid_trusted && info->si_pid == getpid())) { |
sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); |
} |
- CrashContext context; |
+ |
// Fill in all the holes in the struct to make Valgrind happy. |
- memset(&context, 0, sizeof(context)); |
- memcpy(&context.siginfo, info, sizeof(siginfo_t)); |
- memcpy(&context.context, uc, sizeof(struct ucontext)); |
+ 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:
|
+ memcpy(&g_crash_context_.siginfo, info, sizeof(siginfo_t)); |
+ memcpy(&g_crash_context_.context, uc, sizeof(struct ucontext)); |
#if defined(__aarch64__) |
- struct ucontext *uc_ptr = (struct ucontext*)uc; |
- struct fpsimd_context *fp_ptr = |
+ struct ucontext* uc_ptr = (struct ucontext*)uc; |
+ struct fpsimd_context* fp_ptr = |
(struct fpsimd_context*)&uc_ptr->uc_mcontext.__reserved; |
if (fp_ptr->head.magic == FPSIMD_MAGIC) { |
- memcpy(&context.float_state, fp_ptr, sizeof(context.float_state)); |
+ memcpy(&g_crash_context_.float_state, fp_ptr, |
+ sizeof(g_crash_context_.float_state)); |
} |
-#elif !defined(__ARM_EABI__) && !defined(__mips__) |
+#elif !defined(__ARM_EABI__) && !defined(__mips__) |
// FP state is not part of user ABI on ARM Linux. |
// In case of MIPS Linux FP state is already part of struct ucontext |
// and 'float_state' is not a member of CrashContext. |
- struct ucontext *uc_ptr = (struct ucontext*)uc; |
+ struct ucontext* uc_ptr = (struct ucontext*)uc; |
if (uc_ptr->uc_mcontext.fpregs) { |
- memcpy(&context.float_state, |
- uc_ptr->uc_mcontext.fpregs, |
- sizeof(context.float_state)); |
+ memcpy(&g_crash_context_.float_state, uc_ptr->uc_mcontext.fpregs, |
+ sizeof(g_crash_context_.float_state)); |
} |
#endif |
- context.tid = syscall(__NR_gettid); |
+ g_crash_context_.tid = syscall(__NR_gettid); |
if (crash_handler_ != NULL) { |
- if (crash_handler_(&context, sizeof(context), callback_context_)) { |
+ if (crash_handler_(&g_crash_context_, sizeof(g_crash_context_), |
+ callback_context_)) { |
return true; |
} |
} |
- return GenerateDump(&context); |
+ return GenerateDump(&g_crash_context_); |
} |
// This is a public interface to HandleSignal that allows the client to |