OS X 10.6 Snow Leopard 中的 NSTask 问题
有其他人看到或听说过 10.6 中 NSTask 的任何问题吗?
这段代码昨天运行得很好,今天就失效了。
NSTask *task = [converter task];
[task waitUntilExit];
NSLog(@"Task did complete");
该任务执行了它应该执行的操作(我检查了输出,结果很好),但程序将在 waitUntilExit
方法处无限期地等待。我有一些使用类似代码的单元测试,它们之前都已通过,但截至昨天,它们不再工作。
Has anyone else seen or heard of any issues with NSTask in 10.6?
This code worked fine yesterday, and is not working today.
NSTask *task = [converter task];
[task waitUntilExit];
NSLog(@"Task did complete");
The task does what it's supposed to do (I checked the output and it's fine), but the program will wait indefinitely at the waitUntilExit
method. I have a few unit tests that use similar code, they all had passed previously, but as of yesterday, they are no longer working.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您需要添加以下魔术行:
You need to add the following magic line:
(1) 您是否以任何方式处理任务的输出?如果是这样,如果您不读取 & 输出的缓冲可能会阻塞。沿途处理数据。
(2) 您的任务在终止前是否等待 stdin 上的 EOL?如果是这样,您将需要获取标准输入并显式关闭它。
正如 Peter 所说,检查 ps 看看你的任务是否仍在运行。如果是,请使用
sample
对其进行采样以了解其用途。(1) Do you process the output from the task in any way? If so, the buffering of the output can block if you don't read & process the data along the way.
(2) Does your task wait for EOL on stdin before terminating? If so, you'll want to grab stdin and explicitly close it.
As Peter said, check ps to see if your task is still running. If it is, use
sample
to sample it to figure out what it is up to.可能 - 我注意到我在 10.6 上的一些代码有一个问题,听起来很像你的问题。
我需要以完全异步的方式获取一些网络信息(主要是关于 BGP 和 AS 的信息)。对我来说,理想的解决方案是将特殊的 DNS TXT 记录请求发送到可公开访问的 DNS 服务器,但 Cocoa/Core Foundation 不提供用于执行此类奇怪 DNS 请求的 API。另一种方法是使用 shell% whois -h IP 'SPECIAL REQUEST' 并从输出中解析出相关信息。我可以在几个小时内启动并运行它,然后再回来并提出真正的解决方案。非常 hacky,但比 1) 找到合适的异步 DNS 库和 2) 加快其 API 的速度并可能为其编写包装器要快得多。
因此,我创建了一个类来分叉后台线程,然后使用 NSTask 来启动 whois 请求。后台线程位于 NSRunLoop 循环中来处理结果,但每隔约 1/10 秒检查一次,看看 NSTask 是否因某种原因死亡,或者是否 < code>[NSThread isCanceled] 等。它还会注册
NSApplicationWillTerminateNotification
通知,以便在应用程序退出时它可以进行适当的清理。好吧,从 10.6 开始……我不能再“快速”退出了。在 10.5 上,一切都如玻璃般光滑,应用程序会立即退出,至少在感知上是这样。在 10.6 下,退出会导致应用程序“挂起”。调试显示,在尝试清理挥之不去的 whois NSTask 时,一切都被挂起。由于我通过这种方式获得的信息对于应用程序功能来说都不是至关重要的(了解一些信息是额外的,很高兴),所以我只是有点下注并停止尝试获取信息作为权宜之计。
快速调试问题表明主应用程序在尝试获取实例
NSLock
时被阻止。有趣的是,如果我不理会它,应用程序最终会正常退出——从 10-20 秒到几分钟不等。10.5 和 10.6 之间发生了一些变化,导致代码被括在[NSLock lock] 内。 . [NSLock解锁]
阻止“需要很长时间”。不过,我还没有找到发生这种情况的地方(还不是优先事项)......但其中一件事是终止后台NSTask
如果它仍在运行并“等待它完成” ' 在它可以安全地删除诸如NSPipe
之类的东西之前。DUP:这可能是一个愚蠢的答案......我的第一个似乎已经消失在其中之一?
Possibly- I noticed a problem with some of my code on 10.6 that sounds suspiciously like your problem.
I needed to get some network info (mostly concerning BGP and AS stuff) in a totally asynchronous manner. The ideal solution for me is to send special DNS TXT record requests to a publicly accessible DNS server, but Cocoa/Core Foundation doesn't provide an API for doing these kinds of odd ball DNS requests. Another way was to use
shell% whois -h IP 'SPECIAL REQUEST'
and just parse out the relevant info from the output. This was something that I could get up and running in a matter of hours and come back later and put in a real solution. Very hacky, but an awful lot faster than 1) finding a suitable asynchronous DNS library and 2) getting up to speed on its API and possibly writing a wrapper for it.So, I created a class that forks off a background thread, and then
NSTask
to kick off thewhois
request. The background thread sits in aNSRunLoop
loop to process the results, but checks every ~1/10 of a second to see if theNSTask
died for some reason, or if[NSThread isCanceled]
, etc etc. It also registers forNSApplicationWillTerminateNotification
notifications so it can do proper cleanup if the app is quitting.Well, as of 10.6... I could no longer quit 'quickly'. On 10.5, everything is glass smooth, and the app quits instantly, at least perceptually. Under 10.6, quitting causes the app to 'hang'. Debugging showed that everything was getting hung up trying to clean up lingering
whois NSTask
s. Since none of the information I get this way is critical to the apps functionality (it's extra, nice to know kind of info), I just sort of punted and stopped trying to get the info as a stop gap solution.The quick passes at debugging the problem showed that the main app was blocking on trying to acquire the instances
NSLock
. What's interesting is that if I just leave it alone, the application does eventually exit normally- anywhere from 10-20 seconds to minutes.. something changed between 10.5 and 10.6 that is causing code bracketed inside a[NSLock lock] ... [NSLock unlock]
block to 'take a long time'. I have yet to track down where that's happening, though (not yet a priority).... but one of those things is terminating the backgroundNSTask
if it's still running and 'waiting for it to finish up' before it can safely get rid of stuff like itsNSPipe
.DUP: This might be a dupe answer... my first one seems to have vanished in to the either?
检查 ps、top 或活动监视器。确保您的进程已退出。
Check ps, top, or Activity Monitor. Make sure your process exited.
不确定这是否有帮助,但您可以尝试在单独的线程上进行等待:
我遇到了一个问题,任务完成时我没有收到 NSNotification,这解决了它。显然 10.6 下的 NSTask 实现存在一些错误...
Not sure if that helps, but you can try doing the wait on a separate thread:
I had a problem where I didn't get the NSNotification when the task finished, and this fixed it. Apparently there are some bugs in the NSTask implementation under 10.6...