mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-08 23:42:25 +02:00
Use execve to "launch" Interface on macOS
Co-authored-by: dante ruiz <dante@highfidelity.io>
This commit is contained in:
parent
a097d567ca
commit
cff4f9da19
4 changed files with 102 additions and 16 deletions
|
@ -43,6 +43,8 @@ set(src_files
|
|||
src/LaunchInterface.h
|
||||
src/CustomUI.h
|
||||
src/CustomUI.m
|
||||
src/NSTask+NSTaskExecveAdditions.h
|
||||
src/NSTask+NSTaskExecveAdditions.m
|
||||
src/main.mm
|
||||
nib/Window.xib
|
||||
nib/SplashScreen.xib
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#import "ProcessScreen.h"
|
||||
#import "ErrorViewController.h"
|
||||
#import "Settings.h"
|
||||
#import "NSTask+NSTaskExecveAdditions.h"
|
||||
|
||||
@interface Launcher ()
|
||||
|
||||
|
@ -456,8 +457,6 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
|||
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
|
||||
NSURL *url = [NSURL fileURLWithPath:[workspace fullPathForApplication:[[self getAppPath] stringByAppendingString:@"interface.app/Contents/MacOS/interface"]]];
|
||||
|
||||
NSError *error = nil;
|
||||
|
||||
NSString* contentPath = [[self getDownloadPathForContentAndScripts] stringByAppendingString:@"content"];
|
||||
NSString* displayName = [ self displayName];
|
||||
NSString* scriptsPath = [[self getAppPath] stringByAppendingString:@"interface.app/Contents/Resources/scripts/simplifiedUIBootstrapper.js"];
|
||||
|
@ -484,13 +483,11 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
|||
@"--no-updater",
|
||||
@"--no-launcher", nil];
|
||||
}
|
||||
[workspace launchApplicationAtURL:url options:NSWorkspaceLaunchNewInstance configuration:[NSDictionary dictionaryWithObject:arguments forKey:NSWorkspaceLaunchConfigurationArguments] error:&error];
|
||||
|
||||
[NSTimer scheduledTimerWithTimeInterval: 3.0
|
||||
target: self
|
||||
selector: @selector(exitLauncher:)
|
||||
userInfo:nil
|
||||
repeats: NO];
|
||||
NSTask *task = [[NSTask alloc] init];
|
||||
task.launchPath = [url path];
|
||||
task.arguments = arguments;
|
||||
[task replaceThisProcess];
|
||||
}
|
||||
|
||||
- (ProcessState) currentProccessState
|
||||
|
@ -500,15 +497,20 @@ static BOOL const DELETE_ZIP_FILES = TRUE;
|
|||
|
||||
- (void) callLaunchInterface:(NSTimer*) timer
|
||||
{
|
||||
NSWindow* mainWindow = [[[NSApplication sharedApplication] windows] objectAtIndex:0];
|
||||
|
||||
ProcessScreen* processScreen = [[ProcessScreen alloc] initWithNibName:@"ProcessScreen" bundle:nil];
|
||||
[[[[NSApplication sharedApplication] windows] objectAtIndex:0] setContentViewController: processScreen];
|
||||
[self launchInterface];
|
||||
}
|
||||
|
||||
|
||||
- (void) exitLauncher:(NSTimer*) timer
|
||||
{
|
||||
[NSApp terminate:self];
|
||||
[mainWindow setContentViewController: processScreen];
|
||||
@try
|
||||
{
|
||||
[self launchInterface];
|
||||
}
|
||||
@catch (NSException *exception)
|
||||
{
|
||||
NSLog(@"Caught exception: Name: %@, Reason: %@", exception.name, exception.reason);
|
||||
ErrorViewController* errorViewController = [[ErrorViewController alloc] initWithNibName:@"ErrorScreen" bundle:nil];
|
||||
[mainWindow setContentViewController: errorViewController];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
9
launchers/darwin/src/NSTask+NSTaskExecveAdditions.h
Normal file
9
launchers/darwin/src/NSTask+NSTaskExecveAdditions.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NSTask (NSTaskExecveAdditions)
|
||||
- (void) replaceThisProcess;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
73
launchers/darwin/src/NSTask+NSTaskExecveAdditions.m
Normal file
73
launchers/darwin/src/NSTask+NSTaskExecveAdditions.m
Normal file
|
@ -0,0 +1,73 @@
|
|||
#import "NSTask+NSTaskExecveAdditions.h"
|
||||
|
||||
#import <libgen.h>
|
||||
|
||||
char **
|
||||
toCArray(NSArray<NSString *> *array)
|
||||
{
|
||||
// Add one to count to accommodate the NULL that terminates the array.
|
||||
char **cArray = (char **) calloc([array count] + 1, sizeof(char *));
|
||||
if (cArray == NULL) {
|
||||
NSException *exception = [NSException
|
||||
exceptionWithName:@"MemoryException"
|
||||
reason:@"malloc failed"
|
||||
userInfo:nil];
|
||||
@throw exception;
|
||||
}
|
||||
char *str;
|
||||
for (int i = 0; i < [array count]; i++) {
|
||||
str = (char *) [array[i] UTF8String];
|
||||
if (str == NULL) {
|
||||
NSException *exception = [NSException
|
||||
exceptionWithName:@"NULLStringException"
|
||||
reason:@"UTF8String was NULL"
|
||||
userInfo:nil];
|
||||
@throw exception;
|
||||
}
|
||||
if (asprintf(&cArray[i], "%s", str) == -1) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
free(cArray[j]);
|
||||
}
|
||||
free(cArray);
|
||||
NSException *exception = [NSException
|
||||
exceptionWithName:@"MemoryException"
|
||||
reason:@"malloc failed"
|
||||
userInfo:nil];
|
||||
@throw exception;
|
||||
}
|
||||
}
|
||||
return cArray;
|
||||
}
|
||||
|
||||
@implementation NSTask (NSTaskExecveAdditions)
|
||||
|
||||
- (void) replaceThisProcess {
|
||||
char **args = toCArray([@[[self launchPath]] arrayByAddingObjectsFromArray:[self arguments]]);
|
||||
|
||||
NSMutableArray *env = [[NSMutableArray alloc] init];
|
||||
NSDictionary* environvment = [[NSProcessInfo processInfo] environment];
|
||||
for (NSString* key in environvment) {
|
||||
NSString* environmentVariable = [[key stringByAppendingString:@"="] stringByAppendingString:environvment[key]];
|
||||
[env addObject:environmentVariable];
|
||||
}
|
||||
|
||||
char** envp = toCArray(env);
|
||||
// `execve` replaces the current process with `path`.
|
||||
// It will only return if it fails to replace the current process.
|
||||
chdir(dirname(args[0]));
|
||||
execve(args[0], (char * const *)args, envp);
|
||||
|
||||
// If we're here `execve` failed. :(
|
||||
for (int i = 0; i < [[self arguments] count]; i++) {
|
||||
free((void *) args[i]);
|
||||
}
|
||||
free((void *) args);
|
||||
|
||||
NSException *exception = [NSException
|
||||
exceptionWithName:@"ExecveException"
|
||||
reason:[NSString stringWithFormat:@"couldn't execve: %s", strerror(errno)]
|
||||
userInfo:nil];
|
||||
@throw exception;
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in a new issue