bug 573290 - use libc / syscall wrappers for Linux in exception handler callback to avoid dynamic linker. rs=khuey a=fixing orange
authorTed Mielczarek <ted.mielczarek@gmail.com>
Thu, 29 Jul 2010 11:31:07 -0400
changeset 48719 43e26f5fad26726ecb7d0a0f8bf517fde6caef64
parent 48718 8fbcb029ca0a2e120baa2ccf41674dd0439965de
child 48720 d87b40f23fa7f80a47a562f36c4aa30e54c4adef
push idunknown
push userunknown
push dateunknown
reviewerskhuey, fixing
bugs573290
milestone2.0b3pre
bug 573290 - use libc / syscall wrappers for Linux in exception handler callback to avoid dynamic linker. rs=khuey a=fixing orange
toolkit/crashreporter/Makefile.in
toolkit/crashreporter/nsExceptionHandler.cpp
--- a/toolkit/crashreporter/Makefile.in
+++ b/toolkit/crashreporter/Makefile.in
@@ -107,16 +107,15 @@ CPPSRCS = \
 
 FORCE_STATIC_LIB = 1
 
 EXTRA_JS_MODULES = \
   CrashSubmit.jsm \
   $(NULL)
 
 ifdef ENABLE_TESTS
-
 # Temporarily disable the tests on x86-Linux, see bug 573290.
 ifneq ($(OS_ARCH)_$(TARGET_XPCOM_ABI),Linux_x86-gcc3)
 TOOL_DIRS = test
 endif
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -59,18 +59,19 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include "mac_utils.h"
 #elif defined(XP_LINUX)
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsIINIParser.h"
+#include "common/linux/linux_libc_support.h"
+#include "common/linux/linux_syscall_support.h"
 #if defined(MOZ_IPC)
-#  include "common/linux/linux_syscall_support.h"
 #  include "client/linux/crash_generation/client_info.h"
 #  include "client/linux/crash_generation/crash_generation_server.h"
 #endif
 #include "client/linux/handler/exception_handler.h"
 #include <fcntl.h>
 #include <sys/types.h>
 #include <unistd.h>
 #elif defined(XP_SOLARIS)
@@ -132,22 +133,31 @@ typedef std::wstring xpstring;
 #else
 #define XP_TTOA(time, buffer, base) _i64toa(time, buffer, base)
 #endif
 #else
 typedef char XP_CHAR;
 typedef std::string xpstring;
 #define CONVERT_UTF16_TO_XP_CHAR(x) NS_ConvertUTF16toUTF8(x)
 #define CONVERT_XP_CHAR_TO_UTF16(x) NS_ConvertUTF8toUTF16(x)
-#define XP_STRLEN(x) strlen(x)
 #define CRASH_REPORTER_FILENAME "crashreporter"
 #define PATH_SEPARATOR "/"
 #define XP_PATH_SEPARATOR "/"
 #define XP_PATH_MAX PATH_MAX
+#ifdef XP_LINUX
+#define XP_STRLEN(x) my_strlen(x)
+#define XP_TTOA(time, buffer, base) my_itos(buffer, time, sizeof(buffer))
+#else
+#define XP_STRLEN(x) strlen(x)
 #define XP_TTOA(time, buffer, base) sprintf(buffer, "%ld", time)
+#define sys_close close
+#define sys_fork fork
+#define sys_open open
+#define sys_write write
+#endif
 #endif // XP_WIN32
 
 static const XP_CHAR dumpFileExtension[] = {'.', 'd', 'm', 'p',
                                             '\0'}; // .dmp
 static const XP_CHAR extraFileExtension[] = {'.', 'e', 'x', 't',
                                              'r', 'a', '\0'}; // .extra
 
 static google_breakpad::ExceptionHandler* gExceptionHandler = nsnull;
@@ -263,17 +273,24 @@ bool MinidumpCallback(const XP_CHAR* dum
   size = XP_PATH_MAX;
   p = Concat(extraDataPath, dump_path, &size);
   p = Concat(p, XP_PATH_SEPARATOR, &size);
   p = Concat(p, minidump_id, &size);
   Concat(p, extraFileExtension, &size);
 
   // calculate time since last crash (if possible), and store
   // the time of this crash.
-  time_t crashTime = time(NULL);
+  time_t crashTime;
+#ifdef XP_LINUX
+  struct kernel_timeval tv;
+  sys_gettimeofday(&tv, NULL);
+  crashTime = tv.tv_sec;
+#else
+  crashTime = time(NULL);
+#endif
   time_t timeSinceLastCrash = 0;
   // stringified versions of the above
   char crashTimeString[32];
   int crashTimeStringLen = 0;
   char timeSinceLastCrashString[32];
   int timeSinceLastCrashStringLen = 0;
 
   XP_TTOA(crashTime, crashTimeString, 10);
@@ -290,23 +307,23 @@ bool MinidumpCallback(const XP_CHAR* dum
                               NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
                               NULL);
     if(hFile != INVALID_HANDLE_VALUE) {
       DWORD nBytes;
       WriteFile(hFile, crashTimeString, crashTimeStringLen, &nBytes, NULL);
       CloseHandle(hFile);
     }
 #elif defined(XP_UNIX)
-    int fd = open(lastCrashTimeFilename,
-                  O_WRONLY | O_CREAT | O_TRUNC,
-                  0600);
+    int fd = sys_open(lastCrashTimeFilename,
+                      O_WRONLY | O_CREAT | O_TRUNC,
+                      0600);
     if (fd != -1) {
-      ssize_t ignored = write(fd, crashTimeString, crashTimeStringLen);
+      ssize_t ignored = sys_write(fd, crashTimeString, crashTimeStringLen);
       (void)ignored;
-      close(fd);
+      sys_close(fd);
     }
 #endif
   }
 
 #if defined(XP_WIN32)
   XP_CHAR cmdLine[CMDLINE_SIZE];
   size = CMDLINE_SIZE;
   p = Concat(cmdLine, L"\"", &size);
@@ -357,43 +374,43 @@ bool MinidumpCallback(const XP_CHAR* dum
     CloseHandle( pi.hProcess );
     CloseHandle( pi.hThread );
   }
   // we're not really in a position to do anything if the CreateProcess fails
   TerminateProcess(GetCurrentProcess(), 1);
 #elif defined(XP_UNIX)
   if (!crashReporterAPIData->IsEmpty()) {
     // write out API data
-    int fd = open(extraDataPath,
-                  O_WRONLY | O_CREAT | O_TRUNC,
-                  0666);
+    int fd = sys_open(extraDataPath,
+                      O_WRONLY | O_CREAT | O_TRUNC,
+                      0666);
 
     if (fd != -1) {
       // not much we can do in case of error
-      ssize_t ignored = write(fd, crashReporterAPIData->get(),
-                              crashReporterAPIData->Length());
-      ignored = write(fd, kCrashTimeParameter, kCrashTimeParameterLen);
-      ignored = write(fd, crashTimeString, crashTimeStringLen);
-      ignored = write(fd, "\n", 1);
+      ssize_t ignored = sys_write(fd, crashReporterAPIData->get(),
+                                  crashReporterAPIData->Length());
+      ignored = sys_write(fd, kCrashTimeParameter, kCrashTimeParameterLen);
+      ignored = sys_write(fd, crashTimeString, crashTimeStringLen);
+      ignored = sys_write(fd, "\n", 1);
       if (timeSinceLastCrash != 0) {
-        ignored = write(fd, kTimeSinceLastCrashParameter,
+        ignored = sys_write(fd, kTimeSinceLastCrashParameter,
                         kTimeSinceLastCrashParameterLen);
-        ignored = write(fd, timeSinceLastCrashString,
+        ignored = sys_write(fd, timeSinceLastCrashString,
                         timeSinceLastCrashStringLen);
-        ignored = write(fd, "\n", 1);
+        ignored = sys_write(fd, "\n", 1);
       }
-      close (fd);
+      sys_close(fd);
     }
   }
 
   if (!doReport) {
     return returnValue;
   }
 
-  pid_t pid = fork();
+  pid_t pid = sys_fork();
 
   if (pid == -1)
     return false;
   else if (pid == 0) {
     // need to clobber this, as libcurl might load NSS,
     // and we want it to load the system NSS.
     unsetenv("LD_LIBRARY_PATH");
     (void) execl(crashReporterPath,
@@ -524,26 +541,16 @@ nsresult SetExceptionHandler(nsILocalFil
 
 #elif defined(XP_UNIX)
   // we assume it's always /tmp on unix systems
   nsCString tempPath = NS_LITERAL_CSTRING("/tmp/");
 #else
 #error "Implement this for your platform"
 #endif
 
-#ifdef XP_UNIX
-  // During a crash we must not enter the dynamic loader for symbol
-  // resolution. The symbols used from within the exception handler
-  // which might not be called by the application during normal run
-  // should be early-resolved by calling them from here. See bug 573290.
-  int fd = open("/dev/null", O_RDONLY);
-  close(fd);
-  write(-1, NULL, 0);
-#endif
-
   // now set the exception handler
   gExceptionHandler = new google_breakpad::
     ExceptionHandler(tempPath.get(),
 #ifdef XP_WIN
                      FPEFilter,
 #else
                      nsnull,
 #endif