Bug 600362: Make sure updater launches a compatible binary when updating to a 64-bit binary on Mac OS X. r=rstrong r=bsmedberg a=dveditz
authorJosh Aas <joshmoz@gmail.com>
Tue, 11 Jan 2011 22:10:10 -0800
changeset 27292 cffdb5ef7af7d15a9a5b6333544552c11a70c02d
parent 27291 ed88e6a66ef9a4171c48565bb5b564ce76255c4b
child 27293 de9d2e224dbe1df90f12722046577da167aaa16a
push id2632
push userjosh@mozilla.com
push dateWed, 12 Jan 2011 16:03:43 +0000
reviewersrstrong, bsmedberg, dveditz
bugs600362
milestone1.9.1.17pre
Bug 600362: Make sure updater launches a compatible binary when updating to a 64-bit binary on Mac OS X. r=rstrong r=bsmedberg a=dveditz
toolkit/mozapps/update/src/updater/launchchild_osx.mm
--- a/toolkit/mozapps/update/src/updater/launchchild_osx.mm
+++ b/toolkit/mozapps/update/src/updater/launchchild_osx.mm
@@ -32,30 +32,44 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include <Cocoa/Cocoa.h>
+#include <CoreServices/CoreServices.h>
 
 #ifdef __ppc__
 #include <sys/types.h>
 #include <sys/sysctl.h>
 #include <mach/machine.h>
 #endif /* __ppc__ */
 
+bool OnLeopard()
+{
+  static SInt32 gOSXMajor = 0x0;
+  static SInt32 gOSXMinor = 0x0;
+
+  OSErr err = ::Gestalt(gestaltSystemVersionMajor, &gOSXMajor);
+  if (err != noErr) {
+    return false;
+  }
+
+  err = ::Gestalt(gestaltSystemVersionMinor, &gOSXMinor);
+  if (err != noErr) {
+    return false;
+  }
+
+  return (gOSXMajor == 10 && gOSXMinor == 5);
+}
+
 void LaunchChild(int argc, char **argv)
 {
-  int i;
-  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-  NSTask *child = [[[NSTask alloc] init] autorelease];
-  NSMutableArray *args = [[[NSMutableArray alloc] init] autorelease];
-
 #ifdef __ppc__
   // It's possible that the app is a universal binary running under Rosetta
   // translation because the user forced it to.  Relaunching via NSTask would
   // launch the app natively, which the user apparently doesn't want.
   // In that case, try to preserve translation.
 
   // If the sysctl doesn't exist, it's because Rosetta doesn't exist,
   // so don't try to force translation.  In case of other errors, just assume
@@ -71,16 +85,44 @@ void LaunchChild(int argc, char **argv)
     cpu_type_t preferredCPU = CPU_TYPE_POWERPC;
     sysctlbyname("sysctl.proc_exec_affinity", NULL, NULL,
                  &preferredCPU, sizeof(preferredCPU));
 
     // Nothing can be done to handle failure, relaunch anyway.
   }
 #endif /* __ppc__ */
 
-  for (i = 1; i < argc; ++i)
-    [args addObject: [NSString stringWithCString: argv[i]]];
+  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+  NSTask *child = [[[NSTask alloc] init] autorelease];
 
-  [child setLaunchPath: [NSString stringWithCString: argv[0]]];
-  [child setArguments: args];
+  // On Mac OS X 10.5 and later users can be updating to a binary which
+  // will the OS might try to launch in x86_64 mode by default. Mozilla's
+  // x86_64 binaries require Mac OS X 10.6 in order to run so make sure
+  // that we don't try to launch a binary that won't run on Mac OS X 10.5.
+  // Accomplish this by using the command line program "arch" because
+  // "posix_spawnp" (which has a preferred arch attribute) is not available
+  // on Mac OS X 10.4.
+  if (OnLeopard()) {
+    [child setLaunchPath:@"/usr/bin/arch"];
+  }
+  else {
+    [child setLaunchPath:[NSString stringWithCString:argv[0]]];
+  }
+
+  // Set up arguments including the preferred arch and the actual target
+  // binary on Mac OS X 10.5.
+  NSMutableArray *args = [[[NSMutableArray alloc] init] autorelease];
+  if (OnLeopard()) {
+#ifdef __ppc__
+    [args addObject:@"-ppc"];
+#endif
+    [args addObject:@"-i386"];
+    [args addObject:[NSString stringWithCString:argv[0]]];
+  }
+  for (int i = 1; i < argc; ++i) {
+    [args addObject:[NSString stringWithCString:argv[i]]];
+  }
+  [child setArguments:args];
+
   [child launch];
   [pool release];
 }