Bug 440840 - "mailcap handling may fail due to race conditions between thread waiting and system()" [p=mh+mozilla@glandium.org (Mike Hommey) r+sr=bzbarsky]
authorMike Hommey <mh+mozilla@glandium.org>
Sat, 12 Jul 2008 03:46:11 -0500
changeset 15839 3268e0025bba64a630b8c25a66aca91c61d6f172
parent 15838 7f8d627ac32eb79d7cb265d07ad51dedff729c9c
child 15840 cdc93a0afd5e93d4b836d0e01e85c71f0d31795f
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs440840
milestone1.9.1a1pre
Bug 440840 - "mailcap handling may fail due to race conditions between thread waiting and system()" [p=mh+mozilla@glandium.org (Mike Hommey) r+sr=bzbarsky]
uriloader/exthandler/unix/nsOSHelperAppService.cpp
--- a/uriloader/exthandler/unix/nsOSHelperAppService.cpp
+++ b/uriloader/exthandler/unix/nsOSHelperAppService.cpp
@@ -62,17 +62,16 @@
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsHashtable.h"
 #include "nsCRT.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsDirectoryServiceUtils.h"
 #include "prenv.h"      // for PR_GetEnv()
 #include "nsAutoPtr.h"
-#include <stdlib.h>		// for system()
 
 #define LOG(args) PR_LOG(mLog, PR_LOG_DEBUG, args)
 #define LOG_ENABLED() PR_LOG_TEST(mLog, PR_LOG_DEBUG)
 
 static nsresult
 FindSemicolon(nsAString::const_iterator& aSemicolon_iter,
               const nsAString::const_iterator& aEnd_iter);
 static nsresult
@@ -1136,19 +1135,42 @@ nsOSHelperAppService::GetHandlerAndDescr
                   aMozillaFlags = Substring(++equal_sign_iter, semicolon_iter);
                 } else if (optionName.EqualsLiteral("test")) {
                   nsCAutoString testCommand;
                   rv = UnescapeCommand(Substring(++equal_sign_iter, semicolon_iter),
                                        aMajorType,
                                        aMinorType,
                                        aTypeOptions,
                                        testCommand);
+                  if (NS_FAILED(rv))
+                    continue;
+                  nsCOMPtr<nsIProcess> process = do_CreateInstance(NS_PROCESS_CONTRACTID, &rv);
+                  if (NS_FAILED(rv))
+                    continue;
+                  nsCOMPtr<nsILocalFile> file(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv));
+                  if (NS_FAILED(rv))
+                    continue;
+                  rv = file->InitWithNativePath(NS_LITERAL_CSTRING("/bin/sh"));
+                  if (NS_FAILED(rv))
+                    continue;
+                  rv = process->Init(file);
+                  if (NS_FAILED(rv))
+                    continue;
+                  const char *args[] = { "-c", testCommand.get() };
                   LOG(("Running Test: %s\n", testCommand.get()));
-                  // XXX this should not use system(), since that can block the UI thread!
-                  if (NS_SUCCEEDED(rv) && system(testCommand.get()) != 0) {
+                  PRUint32 pid;
+                  rv = process->Run(PR_TRUE, args, 2, &pid);
+                  if (NS_FAILED(rv))
+                    continue;
+                  PRInt32 exitValue;
+                  rv = process->GetExitValue(&exitValue);
+                  if (NS_FAILED(rv))
+                    continue;
+                  LOG(("Exit code: %d\n", exitValue));
+                  if (exitValue) {
                     match = PR_FALSE;
                   }
                 }
               } else {
                 // This is an option that just has a name but no value (eg "copiousoutput")
                 if (optionName.EqualsLiteral("needsterminal")) {
                   match = PR_FALSE;
                 }