forking a process seems to eat up certain lines of code - Objective-C
-
08-07-2019 - |
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?
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
}