【问题标题】:Problems with NSTask in OS X 10.6 Snow LeopardOS X 10.6 Snow Leopard 中的 NSTask 问题
【发布时间】:2009-08-30 15:22:07
【问题描述】:

有其他人在 10.6 中看到或听说过 NSTask 的任何问题吗?

此代码昨天运行良好,今天无法运行。

NSTask *task = [converter task];
[task waitUntilExit];
NSLog(@"Task did complete");

任务完成了它应该做的事情(我检查了输出,一切正常),但程序将无限期地等待waitUntilExit 方法。我有一些使用类似代码的单元测试,它们之前都通过了,但截至昨天,它们不再工作了。

【问题讨论】:

  • 如果你替换一个简单的脚本,它只是拉出口 0;你现在用的那个?
  • 我看到了类似的问题,上面的代码有时会立即完成,有时需要几秒钟或更长时间才能完成。真奇怪!

标签: cocoa macos osx-snow-leopard nstask


【解决方案1】:

你需要添加以下魔法线:

[task setStandardInput:[NSPipe pipe]];

【讨论】:

    【解决方案2】:

    (1) 你是否以任何方式处理任务的输出?如果是这样,如果您不沿途读取和处理数据,输出的缓冲可能会阻塞。

    (2) 您的任务在终止之前是否在标准输入上等待 EOL?如果是这样,您将需要获取标准输入并显式关闭它。

    正如彼得所说,检查 ps 以查看您的任务是否仍在运行。如果是,请使用sample 对其进行采样以了解它在做什么。

    【讨论】:

      【解决方案3】:

      可能 - 我注意到我在 10.6 上的某些代码存在问题,这听起来很像您的问题。

      我需要以完全异步的方式获取一些网络信息(主要是关于 BGP 和 AS 的东西)。对我来说理想的解决方案是将特殊的 DNS TXT 记录请求发送到可公开访问的 DNS 服务器,但 Cocoa/Core Foundation 不提供 API 来执行这些奇怪的 DNS 请求。另一种方法是使用shell% whois -h IP 'SPECIAL REQUEST' 并从输出中解析出相关信息。这是我可以在几个小时内启动并运行的东西,然后再回来并提出一个真正的解决方案。非常 hacky,但比 1) 找到合适的异步 DNS 库和 2) 加快其 API 的速度并可能为其编写包装器要快得多。

      所以,我创建了一个分叉后台线程的类,然后NSTask 启动whois 请求。后台线程位于NSRunLoop 循环中以处理结果,但每隔约1/10 秒检查一次NSTask 是否因某种原因死亡,或者[NSThread isCanceled] 等。它还注册NSApplicationWillTerminateNotification 通知,以便在应用退出时进行适当的清理。

      嗯,从 10.6 开始……我不能再“快速”退出了。在 10.5 上,一切都是玻璃般光滑的,应用程序会立即退出,至少在感知上是这样。在 10.6 下,退出会导致应用“挂起”。调试表明一切都在试图清理挥之不去的whois NSTasks。由于我通过这种方式获得的信息对应用程序功能都不是至关重要的(这是额外的,很高兴知道某种信息),我只是有点下注并停止尝试将信息作为权宜之计解决方案。

      调试问题的快速通过显示主应用程序阻止尝试获取实例NSLock。有趣的是,如果我不理会它,应用程序最终会正常退出——从 10-20 秒到几分钟不等。在 10.5 和 10.6 之间发生了一些变化,导致 [NSLock lock] ... [NSLock unlock] 块内括起来的代码“需要很长时间”时间'。我还没有找到发生的地方,虽然(还不是优先事项)....但是其中一件事是终止背景NSTask,如果它仍在运行并“等待它完成”,然后才能安全摆脱 NSPipe 之类的东西。

      DUP:这可能是一个骗人的答案......我的第一个似乎已经消失在其中一个?

      【讨论】:

      • 这听起来很像我的问题。我没有接触 NSLock,新进程完全通过 NSTask 控制,所以我的问题出在某个地方。糟透了,您(还)没有解决方案,但如果我有任何解决办法,我会及时通知您。
      【解决方案4】:

      检查 ps、top 或 Activity Monitor。确保您的进程已退出。

      【讨论】:

      • 它显示在活动监视器中并正常退出。它正在转换的文件已转换且未损坏。任务似乎正在完成,但不知何故没有通知任何人它已经完成。
      【解决方案5】:

      不确定这是否有帮助,但您可以尝试在单独的线程上等待:

      [NSThread detachNewThreadSelector: @selector(foo) toTarget: self withObject: task];
      
      ...
      
      - (void) foo: (NSTask *) task {
        [task launch];
        [task waitUntilExit];
        ...
      

      我遇到了一个问题,任务完成后我没有收到 NSNotification,这解决了它。显然在 10.6 下的 NSTask 实现中存在一些错误...

      【讨论】:

        猜你喜欢
        • 2010-11-23
        • 2010-11-24
        • 2011-01-13
        • 2010-11-30
        • 2013-07-15
        • 1970-01-01
        • 2013-02-24
        • 1970-01-01
        • 2010-11-22
        相关资源
        最近更新 更多