Question

Here's a simplified version of my code:

- (IBAction)convert:(id)sender
{
    /* these two lines are ignored */
    [textbox setStringValue:@"converting"];
    [convertButton setEnabled:NO];

        pid_t pid;
        if((pid=fork())==-1)
        {
            [log setStringValue:@"couldn't fork a new process."];
            converting = 0;
        [convertButton setEnabled:YES];
            return;
        }else if (pid==0)
        {
            //this is the child
            sleep(2);
            exit(0);
        }else{
            int status;
            waitpid(pid,&status,0);
        }
    }
}

It's a pretty basic fork() call. The problem is, the two lines at the very top (marked with a comment) are ignored...they don't seem to execute until after the forked child exits. Why?

Edit: And what can I do to fix it?

Was it helpful?

Solution

You really really really don't want to call fork() in a Cocoa application. There are about a zillion different gotchas when doing so, mostly related to how various resources like mach ports and other system binding infrastructure survives across the fork() boundary. Threads cause all kinds of hell, too.

Use NSTask instead. While it effectively does fork()/exec() internally, it does so with considerable care to make sure it is done correctly.

OTHER TIPS

Perhaps because your code must return to the main event loop before the GUI can change state? Or, a slight variation, because the thread that runs the GUI is blocked while your code is doing a kernel-level wait()?

bbum got this exactly right. Here's the code I ended up using:

- (IBAction)convert:(id)sender
{
    task = [[NSTask alloc] init];
    [task setLaunchPath: @"/usr/local/bin/lame"];

    NSArray *arguments;
    arguments = [NSArray arrayWithObjects: file,outputFile, nil];
    [task setArguments: arguments];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskFinished:) name:NSTaskDidTerminateNotification object:task];

    [task launch];  
}
- (void) taskFinished:(NSNotification *)note {
    // code here executes after process finishes    
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top