【问题标题】:Determine what's blocking a process on OSX using command line tools?使用命令行工具确定是什么阻止了 OSX 上的进程?
【发布时间】:2012-10-16 11:44:41
【问题描述】:

标题说得最多,真的。在 Linux 上,它会是 easystrace,可能还有 lsof/proc,在 OSX 上它曾经很容易,直到从 OSX Leopard 中删除 truss 以及底层系统调用 (afaik)。

显而易见的方法是使用dtrace 来解决这个问题,但是据我所知dtrace 不会这样做,因为它会在事件发生时捕获它们 - 在我的情况下,阻塞系统调用已经开始.顺便说一句,如果这可以通过dtrace 解决,我很乐意纠正。

我看到 Xcode 的 Instruments 有一个监视器,它通过定期对进程堆栈进行采样来实现类似的功能(不确定它依赖什么系统调用来做到这一点!),也许命令行上的类似功能就足够了(因为它将一直显示堆栈到包装系统调用的库调用)。为了对我的用例有用,这个“采样命令行工具”必须找到并解析它在堆栈上找到的参数,以便确定我们在哪个文件/文件描述符上被阻止。

最后一件事 - 在 Linux 上,您通常可以作为普通用户执行此操作(假设没有 ptrace_scope 技巧)。如果 OSX 解决方案也不需要 root,那就太好了。

【问题讨论】:

  • gdb attach PIDbt 会给你你需要的东西吗?
  • 在 OSX 上可能不是gdb,而是lldb 私下建议的@kobyk。我仍在研究细节,但通过一些手动修补,我能够看到(a)哪个系统调用导致了块(b)它使用lldb 有哪些参数。不需要root,向进程发送了一个信号(不知道为什么)。如果我得到比sample 更好的地方,我会发布一个更完整的答案,如下所示。谢谢!

标签: macos instruments blocking strace dtrace


【解决方案1】:

我提出的解决方案假设如下:

  1. 可以向进程发出信号。
  2. 进程是单线程的(阻塞线程中可能未处理信号)。
  3. 您有 root 访问权限。

dtruss 支持为每个系统调用打印完整的堆栈跟踪(-s 参数)。

示例:

1 号航站楼:

$ python
>>> import socket
>>> s = socket.socket()
>>> s.bind(('', 1234))
>>> s.listen(1)
>>> s.accept() # blocking!

2号航站楼:

$ dtruss -s -p `pgrep python` # or your python pid if you don't have pgrep (port install proctools)

第 1 条:

press Ctrl-C

2号航站楼:

sigreturn(0x7FFF5FBFD660, 0x1E, 0x10031B3D0)             = 0 Err#-2
          libsystem_kernel.dylib`__accept+0xa # HERE IT IS!
          libpython2.7.dylib`PyEval_EvalFrameEx+0x42bf
          libpython2.7.dylib`fast_function+0xb3
...

如果是 sigreturn,堆栈中的第一帧(信号处理程序的拆卸代码:http://linux.die.net/man/2/sigreturn)。

第二帧是我们系统调用的标准库包装器:accept。

【讨论】:

  • 转储堆栈是一个不错的技巧,它比我目前所达到的更远,但是我们错过了我们阻塞的描述符,我们必须用信号干扰进程,我们需要根。我会将此标记为答案,但很高兴收到(并标记...)更好的答案。谢谢老哥!
【解决方案2】:

你可以使用sample:sample PID -e

例如对于nc -l localhost 5999,您将获得一个带有调用图的文件:

Call graph:
    9046 Thread_242504   DispatchQueue_1: com.apple.main-thread  (serial)
      9046 start  (in libdyld.dylib) + 1  [0x7fff90a847e1]
        9046 ???  (in nc)  load address 0x102453000 + 0x166c  [0x10245466c]
          9046 __accept  (in libsystem_kernel.dylib) + 10  [0x7fff94445996]

以及其他有用的信息,例如加载的二进制图像。

【讨论】:

  • 这实际上是一个更好的解决方案,因为它不需要 root 也不会干扰采样过程。谢谢!
猜你喜欢
  • 1970-01-01
  • 2011-04-15
  • 1970-01-01
  • 2014-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-08
  • 2023-03-18
相关资源
最近更新 更多