кажется, что разветвление процесса пожирает определенные строки кода - Objective-C - PullRequest
1 голос
/ 30 ноября 2009

Вот упрощенная версия моего кода:

- (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);
        }
    }
}

Это довольно простой вызов fork (). Проблема в том, что две строки в самом верху (помеченные комментарием) игнорируются ... кажется, что они не выполняются до тех пор, пока после не разветвится дочерний элемент. Почему?

Редактировать : И что я могу сделать, чтобы это исправить?

Ответы [ 3 ]

9 голосов
/ 30 ноября 2009

Вы действительно действительно действительно не хотите звонить fork() в приложении Какао. При этом существует около миллиона различных ошибок, в основном связанных с тем, как различные ресурсы, такие как порты махов и другая инфраструктура привязки системы, выживают за границей fork(). Потоки тоже порождают все виды адов.

Вместо этого используйте NSTask. Хотя он эффективно fork() / exec() внутренне, он делает это с большой осторожностью, чтобы убедиться, что все сделано правильно.

3 голосов
/ 30 ноября 2009

Возможно, потому что ваш код должен вернуться в основной цикл событий, прежде чем графический интерфейс сможет изменить состояние? Или небольшое изменение, потому что поток, выполняющий графический интерфейс, блокируется, пока ваш код выполняет ожидание на уровне ядра ()?

1 голос
/ 30 ноября 2009

bbum понял это правильно. Вот код, который я использовал в итоге:

- (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    
}
...