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
This commit is contained in:
kriswright 2023-09-20 14:46:51 +00:00
Родитель 9d6978c488
Коммит bf4647bc01
2 изменённых файлов: 37 добавлений и 65 удалений

Просмотреть файл

@ -86,72 +86,31 @@ bool IsBinaryArmExecutable(const char* executablePath) {
return isArmExecutable; 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__ #endif // __x86_64__
void LaunchChild(int argc, const char** argv) { void LaunchChild(int argc, const char** argv) {
MacAutoreleasePool pool; MacAutoreleasePool pool;
@try { @try {
bool preferArmLaunch = false; NSString* launchPath = [NSString stringWithUTF8String:argv[0]];
NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:argc - 1];
#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];
}
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
[arguments addObject:[NSString stringWithUTF8String:argv[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) { } @catch (NSException* e) {
NSLog(@"%@: %@", e.name, e.reason); NSLog(@"%@: %@", e.name, e.reason);
} }

Просмотреть файл

@ -26,15 +26,28 @@ void LaunchChildMac(int aArgc, char** aArgv, pid_t* aPid) {
for (int i = 1; i < aArgc; i++) { for (int i = 1; i < aArgc; i++) {
[arguments addObject:[NSString stringWithUTF8String:aArgv[i]]]; [arguments addObject:[NSString stringWithUTF8String:aArgv[i]]];
} }
NSTask* child = [NSTask launchedTaskWithLaunchPath:launchPath __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
arguments:arguments]; NSWorkspaceOpenConfiguration* config =
if (aPid) { [NSWorkspaceOpenConfiguration configuration];
*aPid = [child processIdentifier]; [config setArguments:arguments];
// We used to use waitpid to wait for the process to terminate. This is [config setCreatesNewApplicationInstance:YES];
// incompatible with NSTask and we wait for the process to exit here
// instead. [[NSWorkspace sharedWorkspace]
[child waitUntilExit]; 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) { } @catch (NSException* e) {
NSLog(@"%@: %@", e.name, e.reason); NSLog(@"%@: %@", e.name, e.reason);
} }