Eva*_*ran 8 linux debugging multithreading ptrace
我正在编写一个面向GUI的调试器,主要针对Linux,但我将来会计划到其他操作系统的端口.因为GUI必须始终保持交互,所以我有几个线程处理不同的东西.
主要是我有一个"调试事件"线程,它只是循环等待waitpid返回并将接收到的事件传递给其他线程.我这样做是因为waitpid没有超时,这使得很难将它与其他事件循环集成并保持响应(waitpid可以无限期挂起!).
到目前为止,这种策略对Linux构建工作非常有效.最近我一直试图让我的调试器线程知道(如在调试的应用程序中的线程,而不是调试器本身).
所以我将ptrace选项设置为跟随克隆事件并查找具有高16位设置的状态PTRACE_EVENT_CLONE.然后我PTRACE_GETEVENTMSG用来获取新线程的TID.这一切都适用于我的小型测试工具应用程序.但由于某种原因,当我将该代码放入我的实际调试器时,它失败了.(我得到一个"没有这样的过程"错误代码)
我遇到的一件事是,Windows有一条规则,即只有连接到应用程序的线程才能监听调试事件.Linux的ptrace是否有类似的限制?如果是这样,为什么我的代码适用于其他调试事件?
编辑:
似乎至少waitpid支持从另一个线程等待,该手册页说:
在Linux 2.4之前,线程只是进程的一个特例,因此一个线程无法等待另一个线程的子节点,即使后者属于同一个线程组.但是,POSIX规定了这样的功能,并且从Linux 2.4开始,线程可以并且默认情况下会等待同一线程组中其他线程的子节点.
所以最多这是一个ptrace限制.
小智 5
在实现Maxine VM调试器的Linux特定部分时,我遇到了同样的问题(加上许多其他问题!).您的猜测是正确的,调试器中只有一个线程可以使用ptrace来控制调试对象.我们通过在专用线程上调用ptrace来完成此操作.您可能会发现查看kenai.com/projects/maxine/sources/maxine/show上提供的Maxine源代码中的LinuxTask.java,linuxTask.h和linuxTask.c文件很有用.
据我所知,这是不允许的。任务不能用于ptrace未附加的任务。此外,一个任务最多可以被另一个任务跟踪,因此您不能简单地在每个线程中将其附加一次。我认为这是因为当一个任务附加到另一个任务时,跟踪任务成为被跟踪任务的父级,并且每个任务只能有一个父级。
似乎应该允许多线程跟踪,因为线程是同一进程的一部分,但从实现角度来看,Linux 内核中的线程和进程之间实际上没有太大区别。线程只是一个碰巧与另一个任务共享其大部分资源的任务。
如果有兴趣,可以浏览一下内核中ptrace的源代码。具体看一下,大多数请求ptrace_check_attach都会调用它。如果目标任务的父级不是当前任务,sys_ptrace它会返回(听起来像您收到的错误代码)。-ESRCH