Xcode在运行iOS测试/模拟器后离开僵尸进程

Mik*_*ock 24 xcode zombie-process

在iOS应用程序上使用Xcode几天后,我注意到有超过100个僵尸进程闲逛.似乎每次运行单元测试都有一个,每次我在模拟器中运行完整的应用程序时可能有一个.这是一个示例(清理和截断):

> ps -efj | grep $PRODUCT_NAME
  502  2794   236   0 Wed12AM ??         0:00.00 (MyProduct)  me            2794      0    1 Z      ?? 
  502  2843   236   0 Wed01AM ??         0:00.00 (MyProduct)  me            2843      0    1 Z      ?? 
  502  2886   236   0 Wed01AM ??         0:00.00 (MyProduct)  me            2886      0    1 Z      ?? 
...
  502 13711   236   0 Thu11PM ??         0:00.00 (MyProduct)  me           13711      0    1 Z      ?? 
  502 13770   236   0 Thu11PM ??         0:00.00 (MyProduct)  me           13770      0    1 Z      ?? 
  502 14219   236   0 10:35AM ??         0:00.00 (MyProduct)  me           14219      0    1 Z      ?? 
  502 14280   236   0 10:38AM ??         0:00.00 (MyProduct)  me           14280      0    1 Z      ?? 
Run Code Online (Sandbox Code Playgroud)

倒数第二列中的Z表示它们是僵尸进程.第三列中的236是父PID,launchd在这种情况下属于我的用户.

请注意,某些过程是多天的过程.在此期间我已经退出并重新打开了几次Xcode.

有谁知道为什么会发生这种情况,或者这是否应该引起警报?

kba*_*cki 15

在我的MBP听起来就像是被要求执行STARNET初始化过程的一些特别重的Xcode会议之后,我决定花几分钟寻找到这个僵尸进程废话......毕竟,一个Unix框,不能叉一个无用的Unix盒子.我可能有一些好消息.希望我们能看到.在10.8.2上运行Xcode 4.6.

无论GDB或LLDB使用情况如何,僵尸问题似乎都会发生.在模拟器中运行的应用程序由调试进程拥有 - GDB或LLDB情况下的"debugserver".当你点击"停止"时,在模拟器中运行的应用程序进程变为僵尸.这听起来像是一个不干净的关机序列.

在预感而不是点击"停止"时,我暂停了应用程序,并且在调试控制台(在我的情况下为LLDB)中,我使用"进程分离"从正在运行的应用程序中取消连接.快速ps验证调试服务器不再运行...到目前为止一切顺利!现在,应用程序仍然在模拟器中运行,只是没有进行调试.事实上,现在点击停止按钮是一个无操作.

在模拟器中点击主页按钮返回跳板,然后双击主页按钮并手动关闭应用程序.转到你的命令行,寻找僵尸......没有僵尸!好极了.

所以...下一步是看看是否有合理的方法通过python脚本等执行此类或类似的关闭过程.如果您使用的是GDB,则无法提供帮助.如果我可以通过一个调试控制台命令进行干净关闭,那么只需要习惯不按下损坏的停止按钮.也许有一个资源黑客完全禁用它... :)

编辑#1:几个有趣的花絮......

1.)点击xcode中的Stop按钮直接杀死调试和应用程序进程 - 没有尝试进行干净关闭.应用程序委托applicationWillTerminate和applicationDidEnterBackground中的Printf调试显示正在运行的应用程序因偏见而被杀死 - 控制台中没有显示NSLog.

2)在调试控制台调用[UIApplication的terminateWithSuccess]会导致应用程序终止"正常",但仍留下一个僵尸......有趣的是,如果你有一个断点设置,应用程序将不会终止:

(lldb) expression
Enter expressions, then terminate with an empty line to evaluate:
[(UIApplication *)[UIApplication sharedApplication] terminateWithSuccess]

error: Execution was interrupted, reason: breakpoint 2.1.
The process has been returned to the state before execution.
(lldb) breakpoint disable 2.1
1 breakpoints disabled.
(lldb) expression
Enter expressions, then terminate with an empty line to evaluate:
[(UIApplication *)[UIApplication sharedApplication] terminateWithSuccess]

2013-03-25 01:28:00.186 iPhone Testbed[9481:c07] -[AppDelegate applicationWillTerminate:]
(lldb) 
Run Code Online (Sandbox Code Playgroud)

因此应用程序会经历某种关闭过程,并且会在控制台中终止显示,但我们仍然有一个僵尸,所以它仍然不是一个干净的关闭.

我认为整个事情都与iOS运行时的应用程序有关.直接调整进程时(通过Stop按钮,kill命令,调试控制台等等)iOS运行时不允许进行正确的关闭和清理 - 事实上,跳板仍然认为应用程序在后台运行即使过程不再存在.事实上,我们的iOS和OS X运行时是同一个 - 因此推出拥有僵尸.

所以我认为所有这一切的解决方案是确定iOS级别的干净关闭程序,并且至少能够通过调试控制台执行该程序.要更多地了解UIApplicationExitsOnSuspend标志,看看我是否可以在运行时设置必要的位(而不是plist),以便在调试分离时干净地关闭应用程序...


Hac*_*Saw 3

它们并不特别占用很多空间。

这似乎是 Xcode 机器不正确地终止子进程的产物。

我也有同样的问题,但我注意到,在我的例子中,僵尸属于 ppid 271,它是我名下的 launchd 调用,而不是整个系统。

我很好奇如果我杀死或启动该进程会发生什么。

无论如何,注销或许就能清除丧尸。当然,重新启动会,但在我的书中,这是要避免的。


噢,进展得很糟糕不要杀死你的 launchd,它会毫不客气地杀死你的会话,但不会做任何事情让你恢复它,比如给你一个登录屏幕。

我得看看我是否因为停止 Xcode 而把僵尸抛在了后面。看来这里可能有一些愚蠢的事情。如果你的进程不等待子进程,它就会被僵尸化。如果父母去世了,我认为接下来的事情就会得到它,在这种情况下是启动的。Launchd 应该 wait() 等待它,但也许这会让人困惑?

  • “它们不会特别占用很多空间。”确实如此,但它需要一些更重要的东西:占用您可以创建的进程数量。`fork` 将失败,因此您无法执行 `kill` 事件 (8认同)