分叉进程似乎会占用某些代码行 - Objective-C

发布于 2024-08-12 19:00:28 字数 737 浏览 7 评论 0原文

这是我的代码的简化版本:

- (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() 调用。问题是,最顶部的两行(用注释标记)被忽略......它们似乎直到分叉子进程退出后才执行。为什么?

编辑:我能做些什么来解决这个问题?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

灯角 2024-08-19 19:00:28

你真的真的真的不想在Cocoa应用程序中调用fork()。这样做时会遇到无数不同的问题,主要与各种资源(如 mach 端口和其他系统绑定基础设施)如何跨 fork() 边界生存有关。线程也会导致各种地狱。

请改用 NSTask。虽然它在内部有效地执行了 fork()/exec() 操作,但它在执行此操作时非常小心,以确保正确完成。

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.

鸠魁 2024-08-19 19:00:28

也许是因为您的代码必须在 GUI 更改状态之前返回到主事件循环?或者,略有不同,因为当您的代码执行内核级 wait() 时,运行 GUI 的线程被阻塞?

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()?

三岁铭 2024-08-19 19:00:28

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    
}

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    
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文