fix(debug): target the traced thread and keep the kill from ever blocking
The Go runtime can migrate the debuggee's target-mode goroutine off the process leader before PTRACE_TRACEME, which left the trace relation on a thread the session never addressed: its stops starved the waits on the leader, and a kill sequence that resumed nothing and then blocked in Wait4 hung the whole package. The debuggee now reports the traced thread in the launch handshake and parks with a thread-directed stop, every ptrace request and wait addresses that thread, a SIGURG arriving on a single-step resumes it as a single-step again instead of letting the tracee run uncontrolled, a resume rejected with ESRCH lifts a group-stop with SIGCONT and retries once, and Kill resumes, kills and reaps through non-blocking waits so it returns for a tracee in any state. Assisted-by: GLM 5.3
This commit is contained in:
1 parent
409c8b348d
commit
b5d6f1b46a
14 files changed
+265
-80
No files matched your search
@@ -29,6 +29,18 @@ func mapRWX(code []byte) ([]byte, error) {
|
||||
return mem, nil
|
||||
}
|
||||
|
||||
// parkSelf stops the calling thread for the launch handshake. The stop is
|
||||
// thread-directed on purpose: a process-directed SIGSTOP may be queued on
|
||||
// any of the debuggee's untraced runtime threads, and delivering it there
|
||||
// establishes a group-stop over the whole thread group, which leaves the
|
||||
// traced leader in a plain stop the tracer cannot resume (PTRACE_CONT fails
|
||||
// ESRCH) and the siblings stopped with nobody to continue them. Directed
|
||||
// at the traced thread, the stop always surfaces as the signal-delivery-stop
|
||||
// the handshake consumes.
|
||||
func parkSelf() {
|
||||
syscall.Tgkill(syscall.Getpid(), syscall.Gettid(), syscall.SIGSTOP)
|
||||
}
|
||||
|
||||
// setupBuffers allocates buffers in the debuggee's memory.
|
||||
func setupBuffers(spec string, args []byte, tmpDir string) ([]byte, error) {
|
||||
type bufSpec struct {
|
||||
|
||||
Reference in new issue
Block a user