toolkit/xre/nsSigHandlers.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 * This module is supposed to abstract signal handling away from the other
michael@0 8 * platforms that do not support it.
michael@0 9 */
michael@0 10
michael@0 11 #include "nsSigHandlers.h"
michael@0 12
michael@0 13 #ifdef XP_UNIX
michael@0 14
michael@0 15 #include <signal.h>
michael@0 16 #include <stdio.h>
michael@0 17 #include <string.h>
michael@0 18 #include "prthread.h"
michael@0 19 #include "plstr.h"
michael@0 20 #include "prenv.h"
michael@0 21 #include "nsDebug.h"
michael@0 22 #include "nsXULAppAPI.h"
michael@0 23
michael@0 24 #if defined(LINUX)
michael@0 25 #include <sys/time.h>
michael@0 26 #include <sys/resource.h>
michael@0 27 #include <unistd.h>
michael@0 28 #include <stdlib.h> // atoi
michael@0 29 #ifndef ANDROID // no Android impl
michael@0 30 # include <ucontext.h>
michael@0 31 #endif
michael@0 32 #endif
michael@0 33
michael@0 34 #if defined(SOLARIS)
michael@0 35 #include <sys/resource.h>
michael@0 36 #include <ucontext.h>
michael@0 37 #endif
michael@0 38
michael@0 39 static char _progname[1024] = "huh?";
michael@0 40 static unsigned int _gdb_sleep_duration = 300;
michael@0 41
michael@0 42 // NB: keep me up to date with the same variable in
michael@0 43 // ipc/chromium/chrome/common/ipc_channel_posix.cc
michael@0 44 static const int kClientChannelFd = 3;
michael@0 45
michael@0 46 #if defined(LINUX) && defined(DEBUG) && \
michael@0 47 (defined(__i386) || defined(__x86_64) || defined(PPC))
michael@0 48 #define CRAWL_STACK_ON_SIGSEGV
michael@0 49 #endif
michael@0 50
michael@0 51 #if defined(CRAWL_STACK_ON_SIGSEGV)
michael@0 52
michael@0 53 #include <unistd.h>
michael@0 54 #include "nsISupportsUtils.h"
michael@0 55 #include "nsStackWalk.h"
michael@0 56
michael@0 57 extern "C" {
michael@0 58
michael@0 59 static void PrintStackFrame(void *aPC, void *aSP, void *aClosure)
michael@0 60 {
michael@0 61 char buf[1024];
michael@0 62 nsCodeAddressDetails details;
michael@0 63
michael@0 64 NS_DescribeCodeAddress(aPC, &details);
michael@0 65 NS_FormatCodeAddressDetails(aPC, &details, buf, sizeof(buf));
michael@0 66 fputs(buf, stdout);
michael@0 67 }
michael@0 68
michael@0 69 }
michael@0 70
michael@0 71 void
michael@0 72 ah_crap_handler(int signum)
michael@0 73 {
michael@0 74 printf("\nProgram %s (pid = %d) received signal %d.\n",
michael@0 75 _progname,
michael@0 76 getpid(),
michael@0 77 signum);
michael@0 78
michael@0 79 printf("Stack:\n");
michael@0 80 NS_StackWalk(PrintStackFrame, /* skipFrames */ 2, /* maxFrames */ 0,
michael@0 81 nullptr, 0, nullptr);
michael@0 82
michael@0 83 printf("Sleeping for %d seconds.\n",_gdb_sleep_duration);
michael@0 84 printf("Type 'gdb %s %d' to attach your debugger to this thread.\n",
michael@0 85 _progname,
michael@0 86 getpid());
michael@0 87
michael@0 88 sleep(_gdb_sleep_duration);
michael@0 89
michael@0 90 printf("Done sleeping...\n");
michael@0 91
michael@0 92 _exit(signum);
michael@0 93 }
michael@0 94
michael@0 95 void
michael@0 96 child_ah_crap_handler(int signum)
michael@0 97 {
michael@0 98 if (!getenv("MOZ_DONT_UNBLOCK_PARENT_ON_CHILD_CRASH"))
michael@0 99 close(kClientChannelFd);
michael@0 100 ah_crap_handler(signum);
michael@0 101 }
michael@0 102
michael@0 103 #endif // CRAWL_STACK_ON_SIGSEGV
michael@0 104
michael@0 105 #ifdef MOZ_WIDGET_GTK
michael@0 106 // Need this include for version test below.
michael@0 107 #include <glib.h>
michael@0 108 #endif
michael@0 109
michael@0 110 #if defined(MOZ_WIDGET_GTK) && (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6))
michael@0 111
michael@0 112 static GLogFunc orig_log_func = nullptr;
michael@0 113
michael@0 114 extern "C" {
michael@0 115 static void
michael@0 116 my_glib_log_func(const gchar *log_domain, GLogLevelFlags log_level,
michael@0 117 const gchar *message, gpointer user_data);
michael@0 118 }
michael@0 119
michael@0 120 /* static */ void
michael@0 121 my_glib_log_func(const gchar *log_domain, GLogLevelFlags log_level,
michael@0 122 const gchar *message, gpointer user_data)
michael@0 123 {
michael@0 124 if (log_level & (G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION)) {
michael@0 125 NS_DebugBreak(NS_DEBUG_ASSERTION, message, "glib assertion", __FILE__, __LINE__);
michael@0 126 } else if (log_level & (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)) {
michael@0 127 NS_DebugBreak(NS_DEBUG_WARNING, message, "glib warning", __FILE__, __LINE__);
michael@0 128 }
michael@0 129
michael@0 130 orig_log_func(log_domain, log_level, message, nullptr);
michael@0 131 }
michael@0 132
michael@0 133 #endif
michael@0 134
michael@0 135 #ifdef SA_SIGINFO
michael@0 136 static void fpehandler(int signum, siginfo_t *si, void *context)
michael@0 137 {
michael@0 138 /* Integer divide by zero or integer overflow. */
michael@0 139 /* Note: FPE_INTOVF is ignored on Intel, PowerPC and SPARC systems. */
michael@0 140 if (si->si_code == FPE_INTDIV || si->si_code == FPE_INTOVF) {
michael@0 141 NS_DebugBreak(NS_DEBUG_ABORT, "Divide by zero", nullptr, __FILE__, __LINE__);
michael@0 142 }
michael@0 143
michael@0 144 #ifdef XP_MACOSX
michael@0 145 ucontext_t *uc = (ucontext_t *)context;
michael@0 146
michael@0 147 #if defined(__i386__) || defined(__amd64__)
michael@0 148 _STRUCT_FP_CONTROL *ctrl = &uc->uc_mcontext->__fs.__fpu_fcw;
michael@0 149 ctrl->__invalid = ctrl->__denorm = ctrl->__zdiv = ctrl->__ovrfl = ctrl->__undfl = ctrl->__precis = 1;
michael@0 150
michael@0 151 _STRUCT_FP_STATUS *status = &uc->uc_mcontext->__fs.__fpu_fsw;
michael@0 152 status->__invalid = status->__denorm = status->__zdiv = status->__ovrfl = status->__undfl =
michael@0 153 status->__precis = status->__stkflt = status->__errsumm = 0;
michael@0 154
michael@0 155 __uint32_t *mxcsr = &uc->uc_mcontext->__fs.__fpu_mxcsr;
michael@0 156 *mxcsr |= SSE_EXCEPTION_MASK; /* disable all SSE exceptions */
michael@0 157 *mxcsr &= ~SSE_STATUS_FLAGS; /* clear all pending SSE exceptions */
michael@0 158 #endif
michael@0 159 #endif
michael@0 160 #if defined(LINUX) && !defined(ANDROID)
michael@0 161 ucontext_t *uc = (ucontext_t *)context;
michael@0 162
michael@0 163 #if defined(__i386__)
michael@0 164 /*
michael@0 165 * It seems that we have no access to mxcsr on Linux. libc
michael@0 166 * seems to be translating cw/sw to mxcsr.
michael@0 167 */
michael@0 168 unsigned long int *cw = &uc->uc_mcontext.fpregs->cw;
michael@0 169 *cw |= FPU_EXCEPTION_MASK;
michael@0 170
michael@0 171 unsigned long int *sw = &uc->uc_mcontext.fpregs->sw;
michael@0 172 *sw &= ~FPU_STATUS_FLAGS;
michael@0 173 #endif
michael@0 174 #if defined(__amd64__)
michael@0 175 __uint16_t *cw = &uc->uc_mcontext.fpregs->cwd;
michael@0 176 *cw |= FPU_EXCEPTION_MASK;
michael@0 177
michael@0 178 __uint16_t *sw = &uc->uc_mcontext.fpregs->swd;
michael@0 179 *sw &= ~FPU_STATUS_FLAGS;
michael@0 180
michael@0 181 __uint32_t *mxcsr = &uc->uc_mcontext.fpregs->mxcsr;
michael@0 182 *mxcsr |= SSE_EXCEPTION_MASK; /* disable all SSE exceptions */
michael@0 183 *mxcsr &= ~SSE_STATUS_FLAGS; /* clear all pending SSE exceptions */
michael@0 184 #endif
michael@0 185 #endif
michael@0 186 #ifdef SOLARIS
michael@0 187 ucontext_t *uc = (ucontext_t *)context;
michael@0 188
michael@0 189 #if defined(__i386)
michael@0 190 uint32_t *cw = &uc->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[0];
michael@0 191 *cw |= FPU_EXCEPTION_MASK;
michael@0 192
michael@0 193 uint32_t *sw = &uc->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[1];
michael@0 194 *sw &= ~FPU_STATUS_FLAGS;
michael@0 195
michael@0 196 /* address of the instruction that caused the exception */
michael@0 197 uint32_t *ip = &uc->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[3];
michael@0 198 uc->uc_mcontext.gregs[REG_PC] = *ip;
michael@0 199 #endif
michael@0 200 #if defined(__amd64__)
michael@0 201 uint16_t *cw = &uc->uc_mcontext.fpregs.fp_reg_set.fpchip_state.cw;
michael@0 202 *cw |= FPU_EXCEPTION_MASK;
michael@0 203
michael@0 204 uint16_t *sw = &uc->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw;
michael@0 205 *sw &= ~FPU_STATUS_FLAGS;
michael@0 206
michael@0 207 uint32_t *mxcsr = &uc->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr;
michael@0 208 *mxcsr |= SSE_EXCEPTION_MASK; /* disable all SSE exceptions */
michael@0 209 *mxcsr &= ~SSE_STATUS_FLAGS; /* clear all pending SSE exceptions */
michael@0 210 #endif
michael@0 211 #endif
michael@0 212 }
michael@0 213 #endif
michael@0 214
michael@0 215 void InstallSignalHandlers(const char *ProgramName)
michael@0 216 {
michael@0 217 PL_strncpy(_progname,ProgramName, (sizeof(_progname)-1) );
michael@0 218
michael@0 219 const char *gdbSleep = PR_GetEnv("MOZ_GDB_SLEEP");
michael@0 220 if (gdbSleep && *gdbSleep)
michael@0 221 {
michael@0 222 unsigned int s;
michael@0 223 if (1 == sscanf(gdbSleep, "%u", &s)) {
michael@0 224 _gdb_sleep_duration = s;
michael@0 225 }
michael@0 226 }
michael@0 227
michael@0 228 #if defined(CRAWL_STACK_ON_SIGSEGV)
michael@0 229 if (!getenv("XRE_NO_WINDOWS_CRASH_DIALOG")) {
michael@0 230 void (*crap_handler)(int) =
michael@0 231 GeckoProcessType_Default != XRE_GetProcessType() ?
michael@0 232 child_ah_crap_handler :
michael@0 233 ah_crap_handler;
michael@0 234 signal(SIGSEGV, crap_handler);
michael@0 235 signal(SIGILL, crap_handler);
michael@0 236 signal(SIGABRT, crap_handler);
michael@0 237 }
michael@0 238 #endif // CRAWL_STACK_ON_SIGSEGV
michael@0 239
michael@0 240 #ifdef SA_SIGINFO
michael@0 241 /* Install a handler for floating point exceptions and disable them if they occur. */
michael@0 242 struct sigaction sa, osa;
michael@0 243 sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
michael@0 244 sa.sa_sigaction = fpehandler;
michael@0 245 sigemptyset(&sa.sa_mask);
michael@0 246 sigaction(SIGFPE, &sa, &osa);
michael@0 247 #endif
michael@0 248
michael@0 249 if (XRE_GetProcessType() == GeckoProcessType_Content) {
michael@0 250 /*
michael@0 251 * If the user is debugging a Gecko parent process in gdb and hits ^C to
michael@0 252 * suspend, a SIGINT signal will be sent to the child. We ignore this signal
michael@0 253 * so the child isn't killed.
michael@0 254 */
michael@0 255 signal(SIGINT, SIG_IGN);
michael@0 256 }
michael@0 257
michael@0 258 #if defined(DEBUG) && defined(LINUX)
michael@0 259 const char *memLimit = PR_GetEnv("MOZ_MEM_LIMIT");
michael@0 260 if (memLimit && *memLimit)
michael@0 261 {
michael@0 262 long m = atoi(memLimit);
michael@0 263 m *= (1024*1024);
michael@0 264 struct rlimit r;
michael@0 265 r.rlim_cur = m;
michael@0 266 r.rlim_max = m;
michael@0 267 setrlimit(RLIMIT_AS, &r);
michael@0 268 }
michael@0 269 #endif
michael@0 270
michael@0 271 #if defined(SOLARIS)
michael@0 272 #define NOFILES 512
michael@0 273
michael@0 274 // Boost Solaris file descriptors
michael@0 275 {
michael@0 276 struct rlimit rl;
michael@0 277
michael@0 278 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
michael@0 279
michael@0 280 if (rl.rlim_cur < NOFILES) {
michael@0 281 rl.rlim_cur = NOFILES;
michael@0 282
michael@0 283 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
michael@0 284 perror("setrlimit(RLIMIT_NOFILE)");
michael@0 285 fprintf(stderr, "Cannot exceed hard limit for open files");
michael@0 286 }
michael@0 287 #if defined(DEBUG)
michael@0 288 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
michael@0 289 printf("File descriptors set to %d\n", rl.rlim_cur);
michael@0 290 #endif //DEBUG
michael@0 291 }
michael@0 292 }
michael@0 293 #endif //SOLARIS
michael@0 294
michael@0 295 #if defined(MOZ_WIDGET_GTK) && (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6))
michael@0 296 const char *assertString = PR_GetEnv("XPCOM_DEBUG_BREAK");
michael@0 297 if (assertString &&
michael@0 298 (!strcmp(assertString, "suspend") ||
michael@0 299 !strcmp(assertString, "stack") ||
michael@0 300 !strcmp(assertString, "abort") ||
michael@0 301 !strcmp(assertString, "trap") ||
michael@0 302 !strcmp(assertString, "break"))) {
michael@0 303 // Override the default glib logging function so we get stacks for it too.
michael@0 304 orig_log_func = g_log_set_default_handler(my_glib_log_func, nullptr);
michael@0 305 }
michael@0 306 #endif
michael@0 307 }
michael@0 308
michael@0 309 #elif XP_WIN
michael@0 310
michael@0 311 #include <windows.h>
michael@0 312
michael@0 313 #ifdef _M_IX86
michael@0 314 /*
michael@0 315 * WinNT.h prior to SDK7 does not expose the structure of the ExtendedRegisters for ia86.
michael@0 316 * We known that MxCsr is at offset 0x18 and is a DWORD.
michael@0 317 */
michael@0 318 #define MXCSR(ctx) (*(DWORD *)(((BYTE *)(ctx)->ExtendedRegisters) + 0x18))
michael@0 319 #endif
michael@0 320
michael@0 321 #ifdef _M_X64
michael@0 322 #define MXCSR(ctx) (ctx)->MxCsr
michael@0 323 #endif
michael@0 324
michael@0 325 #if defined(_M_IX86) || defined(_M_X64)
michael@0 326
michael@0 327 #ifdef _M_X64
michael@0 328 #define X87CW(ctx) (ctx)->FltSave.ControlWord
michael@0 329 #define X87SW(ctx) (ctx)->FltSave.StatusWord
michael@0 330 #else
michael@0 331 #define X87CW(ctx) (ctx)->FloatSave.ControlWord
michael@0 332 #define X87SW(ctx) (ctx)->FloatSave.StatusWord
michael@0 333 #endif
michael@0 334
michael@0 335 /*
michael@0 336 * SSE traps raise these exception codes, which are defined in internal NT headers
michael@0 337 * but not winbase.h
michael@0 338 */
michael@0 339 #define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4
michael@0 340 #define STATUS_FLOAT_MULTIPLE_TRAPS 0xC00002B5
michael@0 341
michael@0 342 static LPTOP_LEVEL_EXCEPTION_FILTER gFPEPreviousFilter;
michael@0 343
michael@0 344 LONG __stdcall FpeHandler(PEXCEPTION_POINTERS pe)
michael@0 345 {
michael@0 346 PEXCEPTION_RECORD e = (PEXCEPTION_RECORD)pe->ExceptionRecord;
michael@0 347 CONTEXT *c = (CONTEXT*)pe->ContextRecord;
michael@0 348
michael@0 349 switch (e->ExceptionCode) {
michael@0 350 case STATUS_FLOAT_DENORMAL_OPERAND:
michael@0 351 case STATUS_FLOAT_DIVIDE_BY_ZERO:
michael@0 352 case STATUS_FLOAT_INEXACT_RESULT:
michael@0 353 case STATUS_FLOAT_INVALID_OPERATION:
michael@0 354 case STATUS_FLOAT_OVERFLOW:
michael@0 355 case STATUS_FLOAT_STACK_CHECK:
michael@0 356 case STATUS_FLOAT_UNDERFLOW:
michael@0 357 case STATUS_FLOAT_MULTIPLE_FAULTS:
michael@0 358 case STATUS_FLOAT_MULTIPLE_TRAPS:
michael@0 359 X87CW(c) |= FPU_EXCEPTION_MASK; /* disable all FPU exceptions */
michael@0 360 X87SW(c) &= ~FPU_STATUS_FLAGS; /* clear all pending FPU exceptions */
michael@0 361 #ifdef _M_IX86
michael@0 362 if (c->ContextFlags & CONTEXT_EXTENDED_REGISTERS) {
michael@0 363 #endif
michael@0 364 MXCSR(c) |= SSE_EXCEPTION_MASK; /* disable all SSE exceptions */
michael@0 365 MXCSR(c) &= ~SSE_STATUS_FLAGS; /* clear all pending SSE exceptions */
michael@0 366 #ifdef _M_IX86
michael@0 367 }
michael@0 368 #endif
michael@0 369 return EXCEPTION_CONTINUE_EXECUTION;
michael@0 370 }
michael@0 371 LONG action = EXCEPTION_CONTINUE_SEARCH;
michael@0 372 if (gFPEPreviousFilter)
michael@0 373 action = gFPEPreviousFilter(pe);
michael@0 374
michael@0 375 return action;
michael@0 376 }
michael@0 377
michael@0 378 void InstallSignalHandlers(const char *ProgramName)
michael@0 379 {
michael@0 380 gFPEPreviousFilter = SetUnhandledExceptionFilter(FpeHandler);
michael@0 381 }
michael@0 382
michael@0 383 #else
michael@0 384
michael@0 385 void InstallSignalHandlers(const char *ProgramName)
michael@0 386 {
michael@0 387 }
michael@0 388
michael@0 389 #endif
michael@0 390
michael@0 391 #else
michael@0 392 #error No signal handling implementation for this platform.
michael@0 393 #endif

mercurial