From bf4647bc0142968c31b3464ea050933711e72f38 Mon Sep 17 00:00:00 2001 From: kriswright Date: Wed, 20 Sep 2023 14:46:51 +0000 Subject: [PATCH] Bug 1827651 - Update launch code to use nondeprecated APIs. r=spohl Some changes have to be made to the way we launch to accommodate the new method, noted below. Differential Revision: https://phabricator.services.mozilla.com/D186701 --- .../mozapps/update/updater/launchchild_osx.mm | 71 ++++--------------- toolkit/xre/MacLaunchHelper.mm | 31 +++++--- 2 files changed, 37 insertions(+), 65 deletions(-) diff --git a/toolkit/mozapps/update/updater/launchchild_osx.mm b/toolkit/mozapps/update/updater/launchchild_osx.mm index 917f282d9f57..e2e008a9df5d 100644 --- a/toolkit/mozapps/update/updater/launchchild_osx.mm +++ b/toolkit/mozapps/update/updater/launchchild_osx.mm @@ -86,72 +86,31 @@ bool IsBinaryArmExecutable(const char* executablePath) { return isArmExecutable; } - -// Returns true if the executable provided in |executablePath| should be -// launched with a preference for arm64. After updating from an x64 version -// running under Rosetta, if the update is to a universal binary with arm64 -// support we want to switch to arm64 execution mode. Returns true if those -// conditions are met and the arch(1) utility at |archPath| is executable. -// It should be safe to always launch with arch and fallback to x64, but we -// limit its use to the only scenario it is necessary to minimize risk. -bool ShouldPreferArmLaunch(const char* archPath, const char* executablePath) { - // If not running under Rosetta, we are not on arm64 hardware. - if (!IsProcessRosettaTranslated()) { - return false; - } - - // Ensure the arch(1) utility is present and executable. - NSFileManager* fileMgr = [NSFileManager defaultManager]; - NSString* archPathString = [NSString stringWithUTF8String:archPath]; - if (![fileMgr isExecutableFileAtPath:archPathString]) { - return false; - } - - // Ensure the binary can be run natively on arm64. - return IsBinaryArmExecutable(executablePath); -} #endif // __x86_64__ void LaunchChild(int argc, const char** argv) { MacAutoreleasePool pool; @try { - bool preferArmLaunch = false; - -#if defined(__x86_64__) - // When running under Rosetta, child processes inherit the architecture - // preference of their parent and therefore universal binaries launched - // by an emulated x64 process will launch in x64 mode. If we are running - // under Rosetta, launch the child process with a preference for arm64 so - // that we will switch to arm64 execution if we have just updated from - // x64 to a universal build. This includes if we were already a universal - // build and the user is intentionally running under Rosetta. - preferArmLaunch = ShouldPreferArmLaunch(ARCH_PATH, argv[0]); -#endif // __x86_64__ - - NSString* launchPath; - NSMutableArray* arguments; - - if (preferArmLaunch) { - launchPath = [NSString stringWithUTF8String:ARCH_PATH]; - - // Size the arguments array to include all the arguments - // in |argv| plus two arguments to pass to the arch(1) utility. - arguments = [NSMutableArray arrayWithCapacity:argc + 2]; - [arguments addObject:[NSString stringWithUTF8String:"-arm64"]]; - [arguments addObject:[NSString stringWithUTF8String:"-x86_64"]]; - - // Add the first argument from |argv|. The rest are added below. - [arguments addObject:[NSString stringWithUTF8String:argv[0]]]; - } else { - launchPath = [NSString stringWithUTF8String:argv[0]]; - arguments = [NSMutableArray arrayWithCapacity:argc - 1]; - } + NSString* launchPath = [NSString stringWithUTF8String:argv[0]]; + NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:argc - 1]; for (int i = 1; i < argc; i++) { [arguments addObject:[NSString stringWithUTF8String:argv[i]]]; } - [NSTask launchedTaskWithLaunchPath:launchPath arguments:arguments]; + NSWorkspaceOpenConfiguration* config = + [NSWorkspaceOpenConfiguration configuration]; + [config setArguments:arguments]; + [config setCreatesNewApplicationInstance:YES]; + + [[NSWorkspace sharedWorkspace] + openApplicationAtURL:[NSURL URLWithString:launchPath] + configuration:config + completionHandler:^(NSRunningApplication* child, NSError* error) { + if (error) { + NSLog(@"Failed to run: %@", error); + } + }]; } @catch (NSException* e) { NSLog(@"%@: %@", e.name, e.reason); } diff --git a/toolkit/xre/MacLaunchHelper.mm b/toolkit/xre/MacLaunchHelper.mm index 127e7081e1fa..cae70ca77266 100644 --- a/toolkit/xre/MacLaunchHelper.mm +++ b/toolkit/xre/MacLaunchHelper.mm @@ -26,15 +26,28 @@ void LaunchChildMac(int aArgc, char** aArgv, pid_t* aPid) { for (int i = 1; i < aArgc; i++) { [arguments addObject:[NSString stringWithUTF8String:aArgv[i]]]; } - NSTask* child = [NSTask launchedTaskWithLaunchPath:launchPath - arguments:arguments]; - if (aPid) { - *aPid = [child processIdentifier]; - // We used to use waitpid to wait for the process to terminate. This is - // incompatible with NSTask and we wait for the process to exit here - // instead. - [child waitUntilExit]; - } + __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + NSWorkspaceOpenConfiguration* config = + [NSWorkspaceOpenConfiguration configuration]; + [config setArguments:arguments]; + [config setCreatesNewApplicationInstance:YES]; + + [[NSWorkspace sharedWorkspace] + openApplicationAtURL:[NSURL URLWithString:launchPath] + configuration:config + completionHandler:^(NSRunningApplication* child, NSError* error) { + if (error) { + NSLog(@"Failed to run: %@", error); + } + + if (aPid) { + *aPid = [child processIdentifier]; + } + dispatch_semaphore_signal(semaphore); + }]; + + // We use a semaphore to wait for the application to launch. + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); } @catch (NSException* e) { NSLog(@"%@: %@", e.name, e.reason); }