I am writing a GUI oriented debugger which targets Linux primarily, but I plan ports to other OSes in the future. Because the GUI must stay interactive at all times, I have a few threads handling different things.
我正在编写一个面向GUI的调试器,主要针对Linux,但我将来会计划到其他操作系统的端口。因为GUI必须始终保持交互,所以我有几个线程处理不同的东西。
Primarily I have a "debug event" thread which simply loops waiting for waitpid to return and delivers the received events to the other threads. I do this because waitpid does not have a timeout, which makes it very hard to integrate it with other event loops and keep things responsive (waitpid can hang indefinitely!).
主要是我有一个“调试事件”线程,它只是循环等待waitpid返回并将接收到的事件传递给其他线程。我这样做是因为waitpid没有超时,这使得很难将它与其他事件循环集成并保持响应(waitpid可以无限期挂起!)。
This strategy has worked wonderfully for the Linux builds so far. Lately I've been trying to make my debugger thread aware (as in the threads in the debugged application, not the debugger itself).
到目前为止,这种策略对Linux构建工作非常有效。最近我一直试图让我的调试器线程知道(如在调试应用程序中的线程,而不是调试器本身)。
So I set the ptrace options to follow clone events and look for a status which has the upper 16-bit set to PTRACE_EVENT_CLONE
. Then I use PTRACE_GETEVENTMSG
to get the TID of the new thread. This all works nicely in my small test harness applications. But for some reason, it is failing when i put that code in my actual debugger. (I get a "No such process" error code)
因此,我将ptrace选项设置为跟随克隆事件,并查找将高16位设置为PTRACE_EVENT_CLONE的状态。然后我使用PTRACE_GETEVENTMSG来获取新线程的TID。这一切都适用于我的小型测试工具应用程序。但由于某种原因,当我将该代码放入我的实际调试器时,它失败了。 (我得到一个“没有这样的过程”错误代码)
The one thing that occurred to me is that Windows has a rule that only the thread which attached to an application can listen for debug events. Does Linux's ptrace have a similar limitation? If so, why does my code work for other debug events?
我遇到的一件事是,Windows有一条规则,即只有连接到应用程序的线程才能监听调试事件。 Linux的ptrace是否有类似的限制?如果是这样,为什么我的代码适用于其他调试事件?
EDIT:
编辑:
It seems that at the very least waitpid supports waiting from a different thread, the man page says:
似乎至少waitpid支持从另一个线程等待,该手册页说:
Before Linux 2.4, a thread was just a special case of a process, and as a consequence one thread could not wait on the children of another thread, even when the latter belongs to the same thread group. However, POSIX prescribes such functionality, and since Linux 2.4 a thread can, and by default will, wait on children of other threads in the same thread group.
在Linux 2.4之前,线程只是进程的一个特例,因此一个线程无法等待另一个线程的子节点,即使后者属于同一个线程组。但是,POSIX规定了这样的功能,并且从Linux 2.4开始,线程可以并且默认情况下会等待同一线程组中其他线程的子节点。
So at most this is a ptrace limitation.
所以最多这是一个ptrace限制。
2 个解决方案
#1
4
As far as I can tell, this is not allowed. A task cannot use ptrace
on a task which it has not attached. Also, a task can be traced by at most one other task, so you can't simply attach it once in each thread. I think this is because when one task attaches to another task, the tracing task becomes the parent of the traced task, and each task can only have one parent.
据我所知,这是不允许的。任务不能在未附加的任务上使用ptrace。此外,任务最多可以由一个其他任务跟踪,因此您不能简单地在每个线程中附加一次。我认为这是因为当一个任务附加到另一个任务时,跟踪任务将成为跟踪任务的父级,并且每个任务只能有一个父级。
It seems like multi-thread tracing ought to be allowed because the threads are part of the same process, but implementation-wise, there isn't actually much distinction between threads and processes in the Linux kernel. A thread is just a task that happens to share most of its resources with another task.
似乎应该允许多线程跟踪,因为线程是同一进程的一部分,但是在实现方面,Linux内核中的线程和进程之间实际上没有太大的区别。线程只是一个与其他任务共享大部分资源的任务。
If you're interested, you can browse the source code for ptrace in the kernel. Specifically look at ptrace_check_attach
, which is called by sys_ptrace
for most requests. It returns -ESRCH
(sounds like the error code you're getting) if the target task's parent is not the current task.
如果您有兴趣,可以在内核中浏览ptrace的源代码。具体来看ptrace_check_attach,sys_ptrace为大多数请求调用它。如果目标任务的父项不是当前任务,它将返回-ESRCH(听起来像您正在获取的错误代码)。
#2
5
I had the same issue (plus many others!) while implementing the Linux-specific part of the Maxine VM debugger. You are correct in your guess that only one thread in the debugger can use ptrace to control the debuggee. We accomplish this by making all calls to ptrace on a dedicated thread. You may find it useful to look at the LinuxTask.java, linuxTask.h and linuxTask.c files in the Maxine sources available at kenai.com/projects/maxine/sources/maxine/show
在实现Maxine VM调试器的Linux特定部分时,我遇到了同样的问题(加上许多其他问题!)。您的猜测是正确的,调试器中只有一个线程可以使用ptrace来控制调试对象。我们通过在专用线程上调用ptrace来完成此操作。您可能会发现查看kenai.com/projects/maxine/sources/maxine/show上提供的Maxine源代码中的LinuxTask.java,linuxTask.h和linuxTask.c文件很有用。
#1
4
As far as I can tell, this is not allowed. A task cannot use ptrace
on a task which it has not attached. Also, a task can be traced by at most one other task, so you can't simply attach it once in each thread. I think this is because when one task attaches to another task, the tracing task becomes the parent of the traced task, and each task can only have one parent.
据我所知,这是不允许的。任务不能在未附加的任务上使用ptrace。此外,任务最多可以由一个其他任务跟踪,因此您不能简单地在每个线程中附加一次。我认为这是因为当一个任务附加到另一个任务时,跟踪任务将成为跟踪任务的父级,并且每个任务只能有一个父级。
It seems like multi-thread tracing ought to be allowed because the threads are part of the same process, but implementation-wise, there isn't actually much distinction between threads and processes in the Linux kernel. A thread is just a task that happens to share most of its resources with another task.
似乎应该允许多线程跟踪,因为线程是同一进程的一部分,但是在实现方面,Linux内核中的线程和进程之间实际上没有太大的区别。线程只是一个与其他任务共享大部分资源的任务。
If you're interested, you can browse the source code for ptrace in the kernel. Specifically look at ptrace_check_attach
, which is called by sys_ptrace
for most requests. It returns -ESRCH
(sounds like the error code you're getting) if the target task's parent is not the current task.
如果您有兴趣,可以在内核中浏览ptrace的源代码。具体来看ptrace_check_attach,sys_ptrace为大多数请求调用它。如果目标任务的父项不是当前任务,它将返回-ESRCH(听起来像您正在获取的错误代码)。
#2
5
I had the same issue (plus many others!) while implementing the Linux-specific part of the Maxine VM debugger. You are correct in your guess that only one thread in the debugger can use ptrace to control the debuggee. We accomplish this by making all calls to ptrace on a dedicated thread. You may find it useful to look at the LinuxTask.java, linuxTask.h and linuxTask.c files in the Maxine sources available at kenai.com/projects/maxine/sources/maxine/show
在实现Maxine VM调试器的Linux特定部分时,我遇到了同样的问题(加上许多其他问题!)。您的猜测是正确的,调试器中只有一个线程可以使用ptrace来控制调试对象。我们通过在专用线程上调用ptrace来完成此操作。您可能会发现查看kenai.com/projects/maxine/sources/maxine/show上提供的Maxine源代码中的LinuxTask.java,linuxTask.h和linuxTask.c文件很有用。