зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
9d6978c488
Коммит
bf4647bc01
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче