Backed out changeset 52388a9a6337, bug 592951. a=me
authorJosh Aas <joshmoz@gmail.com>
Wed, 08 Sep 2010 18:19:51 -0400
changeset 52230 9e09716ddaf73e57dbd0d1a50492b0404275f67e
parent 52201 52388a9a63378153bc365b022d913b64e9629bb1
child 52231 0f9e4e3b77eca95fba85ad9557085464d2576644
push idunknown
push userunknown
push dateunknown
reviewersme
bugs592951
milestone2.0b6pre
backs out52388a9a63378153bc365b022d913b64e9629bb1
Backed out changeset 52388a9a6337, bug 592951. a=me
ipc/app/MozillaRuntimeMain.cpp
ipc/chromium/src/base/process_util.h
ipc/chromium/src/base/process_util_mac.mm
ipc/glue/GeckoChildProcessHost.cpp
toolkit/xre/nsEmbedFunctions.cpp
--- a/ipc/app/MozillaRuntimeMain.cpp
+++ b/ipc/app/MozillaRuntimeMain.cpp
@@ -49,23 +49,43 @@
 #include <windows.h>
 // we want a wmain entry point
 #include "nsWindowsWMain.cpp"
 #endif
 
 int
 main(int argc, char* argv[])
 {
+#if defined(MOZ_CRASHREPORTER)
+    if (argc < 2)
+        return 1;
+    const char* const crashReporterArg = argv[--argc];
+
+#  if defined(XP_WIN) || defined(XP_MACOSX)
+    // on windows and mac, |crashReporterArg| is the named pipe on which the
+    // server is listening for requests, or "-" if crash reporting is
+    // disabled.
+    if (0 != strcmp("-", crashReporterArg)
+        && !XRE_SetRemoteExceptionHandler(crashReporterArg))
+        return 1;
+#  elif defined(OS_LINUX)
+    // on POSIX, |crashReporterArg| is "true" if crash reporting is
+    // enabled, false otherwise
+    if (0 != strcmp("false", crashReporterArg)
+        && !XRE_SetRemoteExceptionHandler(NULL))
+        return 1;
+#  else
+#    error "OOP crash reporting unsupported on this platform"
+#  endif   
+#endif // if defined(MOZ_CRASHREPORTER)
+
 #if defined(XP_WIN) && defined(DEBUG_bent)
     MessageBox(NULL, L"Hi", L"Hi", MB_OK);
 #endif
 
-    // Check for the absolute minimum number of args we need to move
-    // forward here. We expect the last arg to be the child process type.
-    if (argc < 1)
-      return 1;
-    GeckoProcessType proctype = XRE_StringToChildProcessType(argv[--argc]);
+    GeckoProcessType proctype =
+        XRE_StringToChildProcessType(argv[argc - 1]);
 
-    nsresult rv = XRE_InitChildProcess(argc, argv, proctype);
+    nsresult rv = XRE_InitChildProcess(argc - 1, argv, proctype);
     NS_ENSURE_SUCCESS(rv, 1);
 
     return 0;
 }
--- a/ipc/chromium/src/base/process_util.h
+++ b/ipc/chromium/src/base/process_util.h
@@ -126,27 +126,46 @@ bool LaunchApp(const std::wstring& cmdli
 // close-on-exec.  |fds_to_remap| defines a mapping of src fd->dest fd to
 // propagate FDs into the child process.
 //
 // As above, if wait is true, execute synchronously. The pid will be stored
 // in process_handle if that pointer is non-null.
 //
 // Note that the first argument in argv must point to the filename,
 // and must be fully specified.
+#ifdef OS_MACOSX
+typedef std::vector<std::pair<int, int> > file_handle_mapping_vector;
+bool LaunchApp(const std::vector<std::string>& argv,
+               const file_handle_mapping_vector& fds_to_remap,
+               bool wait, ProcessHandle* process_handle,
+               task_t* task_handle);
+
+#if defined(OS_LINUX) || defined(OS_MACOSX)
+typedef std::map<std::string, std::string> environment_map;
+bool LaunchApp(const std::vector<std::string>& argv,
+               const file_handle_mapping_vector& fds_to_remap,
+               const environment_map& env_vars_to_set,
+               bool wait, ProcessHandle* process_handle,
+               task_t* task_handle);
+#endif
+#else // !OS_MACOSX
 typedef std::vector<std::pair<int, int> > file_handle_mapping_vector;
 bool LaunchApp(const std::vector<std::string>& argv,
                const file_handle_mapping_vector& fds_to_remap,
                bool wait, ProcessHandle* process_handle);
 
+#if defined(OS_LINUX) || defined(OS_MACOSX)
 typedef std::map<std::string, std::string> environment_map;
 bool LaunchApp(const std::vector<std::string>& argv,
                const file_handle_mapping_vector& fds_to_remap,
                const environment_map& env_vars_to_set,
                bool wait, ProcessHandle* process_handle);
 #endif
+#endif
+#endif
 
 // Executes the application specified by cl. This function delegates to one
 // of the above two platform-specific functions.
 bool LaunchApp(const CommandLine& cl,
                bool wait, bool start_hidden, ProcessHandle* process_handle);
 
 #if defined(OS_WIN)
 // Executes the application specified by |cmd_line| and copies the contents
--- a/ipc/chromium/src/base/process_util_mac.mm
+++ b/ipc/chromium/src/base/process_util_mac.mm
@@ -12,139 +12,217 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
 #include <string>
 
 #include "base/eintr_wrapper.h"
 #include "base/logging.h"
 #include "base/rand_util.h"
+#include "base/scoped_ptr.h"
 #include "base/string_util.h"
 #include "base/time.h"
+#include "chrome/common/mach_ipc_mac.h"
 
 namespace base {
 
-bool LaunchApp(const std::vector<std::string>& argv,
-               const file_handle_mapping_vector& fds_to_remap,
-               bool wait, ProcessHandle* process_handle) {
-  return LaunchApp(argv, fds_to_remap, environment_map(),
-                   wait, process_handle);
+static std::string MachErrorCode(kern_return_t err) {
+  return StringPrintf("0x%x %s", err, mach_error_string(err));
+}
+
+// Forks the current process and returns the child's |task_t| in the parent
+// process.
+static pid_t fork_and_get_task(task_t* child_task) {
+  const int kTimeoutMs = 100;
+  kern_return_t err;
+
+  // Put a random number into the channel name, so that a compromised renderer
+  // can't pretend being the child that's forked off.
+  std::string mach_connection_name = StringPrintf(
+      "org.mozilla.samplingfork.%p.%d",
+      child_task, base::RandInt(0, std::numeric_limits<int>::max()));
+  ReceivePort parent_recv_port(mach_connection_name.c_str());
+
+  // Error handling philosophy: If Mach IPC fails, don't touch |child_task| but
+  // return a valid pid. If IPC fails in the child, the parent will have to wait
+  // until kTimeoutMs is over. This is not optimal, but I've never seen it
+  // happen, and stuff should still mostly work.
+  pid_t pid = fork();
+  switch (pid) {
+    case -1:
+      return pid;
+    case 0: {  // child
+      ReceivePort child_recv_port;
+
+      MachSendMessage child_message(/* id= */0);
+      if (!child_message.AddDescriptor(mach_task_self())) {
+        LOG(ERROR) << "child AddDescriptor(mach_task_self()) failed.";
+        return pid;
+      }
+      mach_port_t raw_child_recv_port = child_recv_port.GetPort();
+      if (!child_message.AddDescriptor(raw_child_recv_port)) {
+        LOG(ERROR) << "child AddDescriptor(" << raw_child_recv_port
+                   << ") failed.";
+        return pid;
+      }
+
+      MachPortSender child_sender(mach_connection_name.c_str());
+      err = child_sender.SendMessage(child_message, kTimeoutMs);
+      if (err != KERN_SUCCESS) {
+        LOG(ERROR) << "child SendMessage() failed: " << MachErrorCode(err);
+        return pid;
+      }
+
+      MachReceiveMessage parent_message;
+      err = child_recv_port.WaitForMessage(&parent_message, kTimeoutMs);
+      if (err != KERN_SUCCESS) {
+        LOG(ERROR) << "child WaitForMessage() failed: " << MachErrorCode(err);
+        return pid;
+      }
+
+      if (parent_message.GetTranslatedPort(0) == MACH_PORT_NULL) {
+        LOG(ERROR) << "child GetTranslatedPort(0) failed.";
+        return pid;
+      }
+      err = task_set_bootstrap_port(mach_task_self(),
+                                    parent_message.GetTranslatedPort(0));
+      if (err != KERN_SUCCESS) {
+        LOG(ERROR) << "child task_set_bootstrap_port() failed: "
+                   << MachErrorCode(err);
+        return pid;
+      }
+      break;
+    }
+    default: {  // parent
+      MachReceiveMessage child_message;
+      err = parent_recv_port.WaitForMessage(&child_message, kTimeoutMs);
+      if (err != KERN_SUCCESS) {
+        LOG(ERROR) << "parent WaitForMessage() failed: " << MachErrorCode(err);
+        return pid;
+      }
+
+      if (child_message.GetTranslatedPort(0) == MACH_PORT_NULL) {
+        LOG(ERROR) << "parent GetTranslatedPort(0) failed.";
+        return pid;
+      }
+      *child_task = child_message.GetTranslatedPort(0);
+
+      if (child_message.GetTranslatedPort(1) == MACH_PORT_NULL) {
+        LOG(ERROR) << "parent GetTranslatedPort(1) failed.";
+        return pid;
+      }
+      MachPortSender parent_sender(child_message.GetTranslatedPort(1));
+
+      MachSendMessage parent_message(/* id= */0);
+      if (!parent_message.AddDescriptor(bootstrap_port)) {
+        LOG(ERROR) << "parent AddDescriptor(" << bootstrap_port << ") failed.";
+        return pid;
+      }
+
+      err = parent_sender.SendMessage(parent_message, kTimeoutMs);
+      if (err != KERN_SUCCESS) {
+        LOG(ERROR) << "parent SendMessage() failed: " << MachErrorCode(err);
+        return pid;
+      }
+      break;
+    }
+  }
+  return pid;
 }
 
 bool LaunchApp(const std::vector<std::string>& argv,
                const file_handle_mapping_vector& fds_to_remap,
-               const environment_map& env_vars_to_set,
-               bool wait, ProcessHandle* process_handle) {
-  bool retval = true;
-
-  char* argv_copy[argv.size() + 1];
-  for (size_t i = 0; i < argv.size(); i++) {
-    argv_copy[i] = const_cast<char*>(argv[i].c_str());
-  }
-  argv_copy[argv.size()] = NULL;
-
-  // Make sure we don't leak any FDs to the child process by marking all FDs
-  // as close-on-exec.
-  SetAllFDsToCloseOnExec();
+               bool wait, ProcessHandle* process_handle,
+               task_t* process_task) {
+  return LaunchApp(argv, fds_to_remap, environment_map(),
+                   wait, process_handle, process_task);
+}
 
-  // Copy _NSGetEnviron() to a new char array and add the variables
-  // in env_vars_to_set.
-  // Existing variables are overwritten by env_vars_to_set.
-  int pos = 0;
-  environment_map combined_env_vars = env_vars_to_set;
-  while((*_NSGetEnviron())[pos] != NULL) {
-    std::string varString = (*_NSGetEnviron())[pos];
-    std::string varName = varString.substr(0, varString.find_first_of('='));
-    std::string varValue = varString.substr(varString.find_first_of('=') + 1);
-    if (combined_env_vars.find(varName) == combined_env_vars.end()) {
-      combined_env_vars[varName] = varValue;
-    }
-    pos++;
-  }
-  int varsLen = combined_env_vars.size() + 1;
+bool LaunchApp(
+    const std::vector<std::string>& argv,
+    const file_handle_mapping_vector& fds_to_remap,
+    const environment_map& environ,
+    bool wait,
+    ProcessHandle* process_handle,
+    task_t* task_handle) {
+  pid_t pid;
 
-  char** vars = new char*[varsLen];
-  int i = 0;
-  for (environment_map::const_iterator it = combined_env_vars.begin();
-       it != combined_env_vars.end(); ++it) {
-    std::string entry(it->first);
-    entry += "=";
-    entry += it->second;
-    vars[i] = strdup(entry.c_str());
-    i++;
-  }
-  vars[i] = NULL;
-
-  posix_spawn_file_actions_t file_actions;
-  if (posix_spawn_file_actions_init(&file_actions) != 0) {
-    for(int j = 0; j < varsLen; j++) {
-      free(vars[j]);
-    }  
-    delete[] vars;
-    return false;
+  if (task_handle == NULL) {
+    pid = fork();
+  } else {
+    // On OS X, the task_t for a process is needed for several reasons. Sadly,
+    // the function task_for_pid() requires privileges a normal user doesn't
+    // have. Instead, a short-lived Mach IPC connection is opened between parent
+    // and child, and the child sends its task_t to the parent at fork time.
+    *task_handle = MACH_PORT_NULL;
+    pid = fork_and_get_task(task_handle);
   }
 
-  // Turn fds_to_remap array into a set of dup2 calls.
-  for (file_handle_mapping_vector::const_iterator it = fds_to_remap.begin();
-       it != fds_to_remap.end();
-       ++it) {
-    int src_fd = it->first;
-    int dest_fd = it->second;
+  if (pid < 0)
+    return false;
+
+  if (pid == 0) {
+    // Child process
 
-    if (src_fd == dest_fd) {
-      int flags = fcntl(src_fd, F_GETFD);
-      if (flags != -1) {
-        fcntl(src_fd, F_SETFD, flags & ~FD_CLOEXEC);
-      }
-    } else {
-      if (posix_spawn_file_actions_adddup2(&file_actions, src_fd, dest_fd) != 0) {
-        posix_spawn_file_actions_destroy(&file_actions);
-        for(int j = 0; j < varsLen; j++) {
-          free(vars[j]);
-        }  
-        delete[] vars;
-        return false;
+    InjectiveMultimap fd_shuffle;
+    for (file_handle_mapping_vector::const_iterator
+        it = fds_to_remap.begin(); it != fds_to_remap.end(); ++it) {
+      fd_shuffle.push_back(InjectionArc(it->first, it->second, false));
+    }
+
+    for (environment_map::const_iterator it = environ.begin();
+         it != environ.end(); ++it) {
+      if (it->first.empty())
+        continue;
+
+      if (it->second.empty()) {
+        unsetenv(it->first.c_str());
+      } else {
+        setenv(it->first.c_str(), it->second.c_str(), 1);
       }
     }
-  }
 
-  int pid = 0;
-  int spawn_succeeded = (posix_spawnp(&pid,
-                                      argv_copy[0],
-                                      &file_actions,
-                                      NULL,
-                                      argv_copy,
-                                      vars) == 0);
+    // Obscure fork() rule: in the child, if you don't end up doing exec*(),
+    // you call _exit() instead of exit(). This is because _exit() does not
+    // call any previously-registered (in the parent) exit handlers, which
+    // might do things like block waiting for threads that don't even exist
+    // in the child.
+    if (!ShuffleFileDescriptors(fd_shuffle))
+      _exit(127);
 
-  for(int j = 0; j < varsLen; j++) {
-    free(vars[j]);
-  }  
-  delete[] vars;
+    // If we are using the SUID sandbox, it sets a magic environment variable
+    // ("SBX_D"), so we remove that variable from the environment here on the
+    // off chance that it's already set.
+    unsetenv("SBX_D");
+
+    CloseSuperfluousFds(fd_shuffle);
 
-  posix_spawn_file_actions_destroy(&file_actions);
-
-  bool process_handle_valid = pid > 0;
-  if (!spawn_succeeded || !process_handle_valid) {
-    retval = false;
+    scoped_array<char*> argv_cstr(new char*[argv.size() + 1]);
+    for (size_t i = 0; i < argv.size(); i++)
+      argv_cstr[i] = const_cast<char*>(argv[i].c_str());
+    argv_cstr[argv.size()] = NULL;
+    execvp(argv_cstr[0], argv_cstr.get());
+    _exit(127);
   } else {
+    // Parent process
     if (wait)
       HANDLE_EINTR(waitpid(pid, 0, 0));
 
     if (process_handle)
       *process_handle = pid;
   }
 
-  return retval;
+  return true;
 }
 
 bool LaunchApp(const CommandLine& cl,
                bool wait, bool start_hidden, ProcessHandle* process_handle) {
   // TODO(playmobil): Do we need to respect the start_hidden flag?
   file_handle_mapping_vector no_files;
-  return LaunchApp(cl.argv(), no_files, wait, process_handle);
+  return LaunchApp(cl.argv(), no_files, wait, process_handle, NULL);
 }
 
 NamedProcessIterator::NamedProcessIterator(const std::wstring& executable_name,
                                            const ProcessFilter* filter)
   : executable_name_(executable_name),
     index_of_kinfo_proc_(0),
     filter_(filter) {
   // Get a snapshot of all of my processes (yes, as we loop it can go stale, but
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -38,20 +38,16 @@
 
 #include "GeckoChildProcessHost.h"
 
 #include "base/command_line.h"
 #include "base/path_service.h"
 #include "base/string_util.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/process_watcher.h"
-#ifdef XP_MACOSX
-#include "chrome/common/mach_ipc_mac.h"
-#include "base/rand_util.h"
-#endif
 
 #include "prprf.h"
 
 #if defined(OS_LINUX)
 #  define XP_LINUX 1
 #endif
 #include "nsExceptionHandler.h"
 
@@ -223,16 +219,19 @@ GeckoChildProcessHost::PerformAsyncLaunc
 
   // We rely on the fact that InitializeChannel() has already been processed
   // on the IO thread before this point is reached.
   if (!GetChannel()) {
     return false;
   }
 
   base::ProcessHandle process;
+#if defined(XP_MACOSX)
+  task_t child_task;
+#endif
 
   // send the child the PID so that it can open a ProcessHandle back to us.
   // probably don't want to do this in the long run
   char pidstring[32];
   PR_snprintf(pidstring, sizeof(pidstring) - 1,
 	      "%ld", base::Process::Current().pid());
 
   const char* const childProcessType =
@@ -307,16 +306,17 @@ GeckoChildProcessHost::PerformAsyncLaunc
   if (mozilla::OmnijarPath()) {
     mozilla::OmnijarPath()->GetNativePath(omnijarPath);
     childArgv.push_back("-omnijar");
     childArgv.push_back(omnijarPath.get());
   }
 #endif
 
   childArgv.push_back(pidstring);
+  childArgv.push_back(childProcessType);
 
 #if defined(MOZ_CRASHREPORTER)
 #  if defined(OS_LINUX)
   int childCrashFd, childCrashRemapFd;
   if (!CrashReporter::CreateNotificationPipeForChild(
         &childCrashFd, &childCrashRemapFd))
     return false;
   if (0 <= childCrashFd) {
@@ -328,73 +328,25 @@ GeckoChildProcessHost::PerformAsyncLaunc
     // "false" == crash reporting disabled
     childArgv.push_back("false");
   }
 #  elif defined(XP_MACOSX)
   childArgv.push_back(CrashReporter::GetChildNotificationPipe());
 #  endif  // OS_LINUX
 #endif
 
-#ifdef XP_MACOSX
-  // Add a mach port to the command line so the child can communicate its
-  // 'task_t' back to the parent.
-  //
-  // Put a random number into the channel name, so that a compromised renderer
-  // can't pretend being the child that's forked off.
-  std::string mach_connection_name = StringPrintf("org.mozilla.machname.%d",
-                                                  base::RandInt(0, std::numeric_limits<int>::max()));
-  childArgv.push_back(mach_connection_name.c_str());
-#endif
-
-  childArgv.push_back(childProcessType);
-
   base::LaunchApp(childArgv, mFileMap,
 #if defined(OS_LINUX) || defined(OS_MACOSX)
                   newEnvVars,
 #endif
-                  false, &process);
-
-#ifdef XP_MACOSX
-  // Wait for the child process to send us its 'task_t' data.
-  const int kTimeoutMs = 1000;
-
-  MachReceiveMessage child_message;
-  ReceivePort parent_recv_port(mach_connection_name.c_str());
-  kern_return_t err = parent_recv_port.WaitForMessage(&child_message, kTimeoutMs);
-  if (err != KERN_SUCCESS) {
-    std::string errString = StringPrintf("0x%x %s", err, mach_error_string(err));
-    LOG(ERROR) << "parent WaitForMessage() failed: " << errString;
-    return false;
-  }
-
-  task_t child_task = child_message.GetTranslatedPort(0);
-  if (child_task == MACH_PORT_NULL) {
-    LOG(ERROR) << "parent GetTranslatedPort(0) failed.";
-    return false;
-  }
-
-  if (child_message.GetTranslatedPort(1) == MACH_PORT_NULL) {
-    LOG(ERROR) << "parent GetTranslatedPort(1) failed.";
-    return false;
-  }
-  MachPortSender parent_sender(child_message.GetTranslatedPort(1));
-
-  MachSendMessage parent_message(/* id= */0);
-  if (!parent_message.AddDescriptor(bootstrap_port)) {
-    LOG(ERROR) << "parent AddDescriptor(" << bootstrap_port << ") failed.";
-    return false;
-  }
-
-  err = parent_sender.SendMessage(parent_message, kTimeoutMs);
-  if (err != KERN_SUCCESS) {
-    std::string errString = StringPrintf("0x%x %s", err, mach_error_string(err));
-    LOG(ERROR) << "parent SendMessage() failed: " << errString;
-    return false;
-  }
+                  false, &process
+#if defined(XP_MACOSX)
+                  , &child_task
 #endif
+                  );
 
 //--------------------------------------------------
 #elif defined(OS_WIN)
 
   FilePath exePath =
     FilePath::FromWStringHack(CommandLine::ForCurrentProcess()->program());
   exePath = exePath.DirName();
 
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -70,19 +70,16 @@
 #include "nsExceptionHandler.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 #include "nsWidgetsCID.h"
 #include "nsXREDirProvider.h"
 
 #include "mozilla/Omnijar.h"
 #ifdef MOZ_IPC
-#if defined(XP_MACOSX)
-#include "chrome/common/mach_ipc_mac.h"
-#endif
 #include "nsX11ErrorHandler.h"
 #include "base/at_exit.h"
 #include "base/command_line.h"
 #include "base/message_loop.h"
 #include "base/process_util.h"
 #include "chrome/common/child_process.h"
 #include "chrome/common/notification_service.h"
 
@@ -307,87 +304,16 @@ XRE_InitChildProcess(int aArgc,
                      GeckoProcessType aProcess)
 {
   NS_ENSURE_ARG_MIN(aArgc, 2);
   NS_ENSURE_ARG_POINTER(aArgv);
   NS_ENSURE_ARG_POINTER(aArgv[0]);
 
   sChildProcessType = aProcess;
 
-  // Complete 'task_t' exchange for Mac OS X. This structure has the same size
-  // regardless of architecture so we don't have any cross-arch issues here.
-#ifdef XP_MACOSX
-  if (aArgc < 1)
-    return 1;
-  const char* const mach_port_name = aArgv[--aArgc];
-
-  const int kTimeoutMs = 1000;
-
-  MachSendMessage child_message(0);
-  if (!child_message.AddDescriptor(mach_task_self())) {
-    NS_WARNING("child AddDescriptor(mach_task_self()) failed.");
-    return 1;
-  }
-
-  ReceivePort child_recv_port;
-  mach_port_t raw_child_recv_port = child_recv_port.GetPort();
-  if (!child_message.AddDescriptor(raw_child_recv_port)) {
-    NS_WARNING("Adding descriptor to message failed");
-    return 1;
-  }
-
-  MachPortSender child_sender(mach_port_name);
-  kern_return_t err = child_sender.SendMessage(child_message, kTimeoutMs);
-  if (err != KERN_SUCCESS) {
-    NS_WARNING("child SendMessage() failed");
-    return 1;
-  }
-
-  MachReceiveMessage parent_message;
-  err = child_recv_port.WaitForMessage(&parent_message, kTimeoutMs);
-  if (err != KERN_SUCCESS) {
-    NS_WARNING("child WaitForMessage() failed");
-    return 1;
-  }
-
-  if (parent_message.GetTranslatedPort(0) == MACH_PORT_NULL) {
-    NS_WARNING("child GetTranslatedPort(0) failed");
-    return 1;
-  }
-  err = task_set_bootstrap_port(mach_task_self(),
-                                parent_message.GetTranslatedPort(0));
-  if (err != KERN_SUCCESS) {
-    NS_WARNING("child task_set_bootstrap_port() failed");
-    return 1;
-  }
-#endif
-  
-#if defined(MOZ_CRASHREPORTER)
-  if (aArgc < 1)
-    return 1;
-  const char* const crashReporterArg = aArgv[--aArgc];
-  
-#  if defined(XP_WIN) || defined(XP_MACOSX)
-  // on windows and mac, |crashReporterArg| is the named pipe on which the
-  // server is listening for requests, or "-" if crash reporting is
-  // disabled.
-  if (0 != strcmp("-", crashReporterArg)
-      && !XRE_SetRemoteExceptionHandler(crashReporterArg))
-    return 1;
-#  elif defined(OS_LINUX)
-  // on POSIX, |crashReporterArg| is "true" if crash reporting is
-  // enabled, false otherwise
-  if (0 != strcmp("false", crashReporterArg)
-      && !XRE_SetRemoteExceptionHandler(NULL))
-    return 1;
-#  else
-#    error "OOP crash reporting unsupported on this platform"
-#  endif   
-#endif // if defined(MOZ_CRASHREPORTER)
-
   gArgv = aArgv;
   gArgc = aArgc;
 
   SetupErrorHandling(aArgv[0]);
   
 #if defined(MOZ_WIDGET_GTK2)
   g_thread_init(NULL);
 #endif