【发布时间】:2015-07-11 21:32:32
【问题描述】:
很抱歉,我无法发布代码来重现此内容。我的问题恰恰是我不知道如何调试这个问题。
我正在使用 ptrace 和 PTRACE_O_TRACEFORK | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEVFORKDONE | PTRACE_O_TRACECLONE 来跟踪一个进程及其子进程(以及子进程的子进程)。该机制很像strace,但用途略有不同,因为我只是跟踪读取或修改的文件。
我的代码(用 C 编写)在 x86-64 架构上的 Debian wheezy 和 Debian jessie 上运行良好(在 i386 上的测试也较少)。当我尝试在 Ubuntu Precise x86-64 虚拟机(使用 3.2.0 内核)上编译和运行时,我遇到了麻烦。
在 Precise 机器上,我有时发现在 vfork 调用发生后我没有立即收到 PTRACE_EVENT_VFORK,而是开始接收事件(几个 SIGSTOP 事件,和一些系统调用)而没有收到PTRACE_EVENT_VFORK 事件。我没有看到正在执行的系统调用有任何可疑之处,而且这种行为是不可预测的。
我不确定如何尝试将其减少到最小的错误情况,而且我真的不知道可能出了什么问题,因为以前从未见过这种丢失事件的行为。可以想象,区别不在于内核,而在于我正在跟踪的构建工具(它是python + gcc的组合)。
有什么建议吗?
【问题讨论】:
-
如果这里没有人可以提供帮助,请尝试在 linux-kernel 邮件列表中询问。 (不太可能有帮助,但值得一试。)作为
ptrace的替代方法,您可以使用LD_PRELOAD trick 拦截对open、read、write和close的调用。还有祝你好运;这听起来很糟糕。 -
我避免使用 LD_PRELOAD,因为我希望我的代码能够跟踪静态链接的二进制文件。坦率地说,我害怕 linux-kernel!大声笑:)
-
我同意 LD_PRELOAD 不是一种理智/有效的方式来做到这一点。不幸的是,我不知道 vfork 跟踪失败的原因。但是,如果您可以使用 seccomp 跟踪模式而不是传统的 ptrace 样式,那么它可能更不容易出错并且更便携。
-
@Nemo,关于静态链接的二进制文件,用 go 编译的任何东西都是主要的反例,这是一个越来越大的漏洞。有机会我会试试你的建议。
-
@DavidRoundy:ptrace 竞争条件是fixed in 3.4,但我不确定它是否会导致您看到的情况。当且仅当您的进程是多线程时,我可以想到另一种可能性,即两个不同的任务导致同一进程停止,而 vfork 一个失败了(STOP/CONT 信号不嵌套或排队)。