Restarting cocoa application

I have an application that checks its command line parameters and stores values ​​in persistent storage. One of them is a password that I don’t want to stick with so that people can see “ps” and friends. The approach that I am currently considering is that after I have saved the values ​​I need, restart the process without command line options. My naive approach is that args [0] is the application path:

NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:[args objectAtIndex:0]];
[task launch];
[task release];
[NSApp terminate:nil];

The child starts up. However, when my application stops, the child does not seem to be an orphan, but gets stuck. Am I just on this?

Additional info: it seems that when I call [NSApp terminate: nil], the NSTask that gets started gets stuck, but if I just exit (), then it works fine. However, I am concerned that the open ones (keychain, plist, etc.) will be in poor condition if I do this.

And note that in most code examples there is some kind of watchdog process that restarts a separate process when necessary. I am trying to restart the current process that is already running from the same process.

+5
source share
4 answers

, ( ) , . .

// gcc -Wall -arch i386 -arch ppc -mmacosx-version-min=10.4 -Os -framework AppKit -o relaunch relaunch.m

#import <AppKit/AppKit.h>

@interface TerminationListener : NSObject
{
    const char *executablePath;
    pid_t parentProcessId;
}

- (void) relaunch;

@end

@implementation TerminationListener

- (id) initWithExecutablePath:(const char *)execPath parentProcessId:(pid_t)ppid
{
    self = [super init];
    if (self != nil) {
        executablePath = execPath;
        parentProcessId = ppid;

        // This adds the input source required by the run loop
        [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(applicationDidTerminate:) name:NSWorkspaceDidTerminateApplicationNotification object:nil];
        if (getppid() == 1) {
            // ppid is launchd (1) => parent terminated already
            [self relaunch];
        }
    }
    return self;
}

- (void) applicationDidTerminate:(NSNotification *)notification
{
    if (parentProcessId == [[[notification userInfo] valueForKey:@"NSApplicationProcessIdentifier"] intValue]) {
        // parent just terminated
        [self relaunch];
    }
}

- (void) relaunch
{
    [[NSWorkspace sharedWorkspace] launchApplication:[NSString stringWithUTF8String:executablePath]];
    exit(0);
}

@end

int main (int argc, const char * argv[])
{
    if (argc != 3) return EXIT_FAILURE;

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    [[[TerminationListener alloc] initWithExecutablePath:argv[1] parentProcessId:atoi(argv[2])] autorelease];
    [[NSApplication sharedApplication] run];

    [pool release];

    return EXIT_SUCCESS;
}
+10

, , . . Cocoa NSTask .

+2

, , . , .

, .

:

....        
        NSString* path = [[NSBundle mainBundle] bundlePath];

        NSString* cmd = [NSString stringWithFormat:@"open -n %@", path];

        [self runCommand:cmd];

        exit(0);
    }

    /// temrinal function

    -(NSString*)runCommand:(NSString*)commandToRun;
    {
        NSTask *task;
        task = [[NSTask alloc] init];
        [task setLaunchPath: @"/bin/sh"];

        NSArray *arguments = [NSArray arrayWithObjects:
                              @"-c" ,
                              [NSString stringWithFormat:@"%@", commandToRun],
                              nil];
        NSLog(@"run command: %@",commandToRun);
        [task setArguments: arguments];

        NSPipe *pipe;
        pipe = [NSPipe pipe];
        [task setStandardOutput: pipe];

        NSFileHandle *file;
        file = [pipe fileHandleForReading];

        [task launch];

        NSData *data;
        data = [file readDataToEndOfFile];

        NSString *output;
        output = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
        return output;
    }
+2

, NSTask , : , NSPipe NSTask, NSTask , , NSTask, , .

, , NSPipe, . , : 1. , 3 : , , , , , , app.isTerminated sleep (1), .

  1. Run the command-line tool in the application using NSTask and set the parameters by convention. Do not use NSPipe, just create an NSTask and run
  2. The application resumes work
0
source

All Articles