MyKillerApp implements a "Relaunch" function. If the "ok" button is pressed, the app launches a tiny standalone app via NSTask, then terminates itself. The standalone app simply does a sleep(1) while() the process which invoked it still exists, (IOW, MyKillerApp that launched it), then calls launchApplication: on [MyKillerApp's bundlePath], which was passed in as a parameter.
It works, in fact it's a beautiful thing... but it only works some of the time. At other times, launchApplication: fails, and I get this output:
From Launch Services:
Taken at face value, the error is clearly absurd, since the path is exactly the same app which just launched the standalone a second ago. ( verified by copy & paste into the shell )
Since my app is sandboxed, I immediately suspected that I'm breaking "the rules", but on reflection...
If it were Sandbox which was offended, then I wouldn't expect the exe to work some or even most of the time, I'd expect Sandbox to come down on me like the zero-tolerance ton of bricks it seems to be in other ways, and my exe would never work at all.
Moreover, if it were Sandbox, I would expect to be denied when I tried to launch the standalone. But I have *never* failed to launch it, it is just an error *in* the standalone when, of all things, I just want to relaunch the app...
Sorry! I'm probably yakking too much already:
Q) Can I implement this kind of relaunch without offending sandbox, and if so, how? Can it be done without resorting to the unappetizing "SMJobBless" sample code paradigm, which requires a user password just to get going ?
Code:
int main( int argc , char *argv[] ) {
SAutoDrain draino;
pid_t parentPID = atoi(argv[2]);
if ( parentPID ) {
ProcessSerialNumber psn;
while ( GetProcessForPID(parentPID, &psn) != procNotFound )
sleep(1);
}
else
NSLog( @"Relaunch::parentPID is zero" );
// zero parentPID is accepted, to allow running the executable from XCode
NSString* appPath = [NSString stringWithCString:argv[1] encoding:NSUTF8StringEncoding];
if ( [[NSWorkspace sharedWorkspace] launchApplication:[appPath stringByExpandingTildeInPath]] )
return 0;
NSLog(@"Relaunch: could not launchApplication with path: %@", [appPath stringByExpandingTildeInPath] );
return -1;
}
It works, in fact it's a beautiful thing... but it only works some of the time. At other times, launchApplication: fails, and I get this output:
Code:
2015-02-22 17:15:52.804 Relaunch[10743:707] LSOpenFromURLSpec() returned -10827 for application /Volumes/temp/builds/MyKillerApp/Debug/MyKillerApp.app path (null).
2015-02-22 17:15:52.805 Relaunch[10743:707] Relaunch: could not launchApplication with path: /Volumes/temp/builds/MyKillerApp/Debug/MyKillerApp.app
From Launch Services:
Code:
kLSNoExecutableErr = -10827, /* The executable is missing*/
Taken at face value, the error is clearly absurd, since the path is exactly the same app which just launched the standalone a second ago. ( verified by copy & paste into the shell )
Since my app is sandboxed, I immediately suspected that I'm breaking "the rules", but on reflection...
If it were Sandbox which was offended, then I wouldn't expect the exe to work some or even most of the time, I'd expect Sandbox to come down on me like the zero-tolerance ton of bricks it seems to be in other ways, and my exe would never work at all.
Moreover, if it were Sandbox, I would expect to be denied when I tried to launch the standalone. But I have *never* failed to launch it, it is just an error *in* the standalone when, of all things, I just want to relaunch the app...
Sorry! I'm probably yakking too much already:
Q) Can I implement this kind of relaunch without offending sandbox, and if so, how? Can it be done without resorting to the unappetizing "SMJobBless" sample code paradigm, which requires a user password just to get going ?