From e7a9daf248180fe9c5d137478a4ccc8b8378a8b4 Mon Sep 17 00:00:00 2001 From: Derek Parker Date: Fri, 3 Apr 2015 10:32:43 -0500 Subject: [PATCH] Return thread directly from trapWait --- proctl/proctl.go | 29 +++++++++-------------------- proctl/proctl_darwin.go | 17 ++++++++++------- proctl/proctl_linux.go | 22 +++++++++++++--------- 3 files changed, 32 insertions(+), 36 deletions(-) diff --git a/proctl/proctl.go b/proctl/proctl.go index 28abb718..4ef93385 100644 --- a/proctl/proctl.go +++ b/proctl/proctl.go @@ -279,32 +279,28 @@ func (dbp *DebuggedProcess) next() error { } for { - tid, err := trapWait(dbp, -1) + thread, err := trapWait(dbp, -1) if err != nil { return err } - th, ok := dbp.Threads[tid] - if !ok { - return fmt.Errorf("unknown thread %d", tid) - } - pc, err := th.CurrentPC() + pc, err := thread.CurrentPC() if err != nil { return err } // Check if we've hit a software breakpoint. If so, reset PC. - if err = th.clearTempBreakpoint(pc - 1); err != nil { + if err = thread.clearTempBreakpoint(pc - 1); err != nil { return err } // Grab the current goroutine for this thread. - tg, err := th.curG() + tg, err := thread.curG() if err != nil { return err } // Make sure we're on the same goroutine. // TODO(dp) take into account goroutine exit. if tg.id == curg.id { - if dbp.CurrentThread.Id != tid { - dbp.SwitchThread(tid) + if dbp.CurrentThread != thread { + dbp.SwitchThread(thread.Id) } break } @@ -322,20 +318,13 @@ func (dbp *DebuggedProcess) Continue() error { } fn := func() error { - wpid, err := trapWait(dbp, -1) + thread, err := trapWait(dbp, -1) if err != nil { return err } - - thread, ok := dbp.Threads[wpid] - if !ok { - return fmt.Errorf("could not find thread for %d", wpid) - } - - if wpid != dbp.CurrentThread.Id { - dbp.SwitchThread(wpid) + if dbp.CurrentThread != thread { + dbp.SwitchThread(thread.Id) } - pc, err := thread.CurrentPC() if err != nil { return err diff --git a/proctl/proctl_darwin.go b/proctl/proctl_darwin.go index 5221e4c1..4896e477 100644 --- a/proctl/proctl_darwin.go +++ b/proctl/proctl_darwin.go @@ -171,17 +171,17 @@ func (dbp *DebuggedProcess) findExecutable() (*macho.File, error) { return exe, nil } -func trapWait(dbp *DebuggedProcess, pid int) (int, error) { +func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, error) { port := C.mach_port_wait(dbp.os.portSet) switch port { case dbp.os.notificationPort: _, status, err := wait(dbp.Pid, 0) if err != nil { - return -1, err + return nil, err } dbp.exited = true - return -1, ProcessExitedError{Pid: dbp.Pid, Status: status.ExitStatus()} + return nil, ProcessExitedError{Pid: dbp.Pid, Status: status.ExitStatus()} case C.MACH_RCV_INTERRUPTED: if !dbp.halt { // Call trapWait again, it seems @@ -189,16 +189,19 @@ func trapWait(dbp *DebuggedProcess, pid int) (int, error) { // process natural death _sometimes_. return trapWait(dbp, pid) } - return -1, ManualStopError{} + return nil, ManualStopError{} case 0: - return -1, fmt.Errorf("error while waiting for task") + return nil, fmt.Errorf("error while waiting for task") } // Since we cannot be notified of new threads on OS X // this is as good a time as any to check for them. dbp.updateThreadList() - - return int(port), nil + thread, ok := dbp.Threads[int(port)] + if !ok { + return nil, fmt.Errorf("could not find thread for %d", port) + } + return thread, nil } func wait(pid, options int) (int, *sys.WaitStatus, error) { diff --git a/proctl/proctl_linux.go b/proctl/proctl_linux.go index c5b2ce5f..a0b7f885 100644 --- a/proctl/proctl_linux.go +++ b/proctl/proctl_linux.go @@ -216,11 +216,11 @@ func stopped(pid int) bool { return false } -func trapWait(dbp *DebuggedProcess, pid int) (int, error) { +func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, error) { for { wpid, status, err := wait(pid, 0) if err != nil { - return -1, fmt.Errorf("wait err %s %d", err, pid) + return nil, fmt.Errorf("wait err %s %d", err, pid) } if wpid == 0 { continue @@ -231,37 +231,41 @@ func trapWait(dbp *DebuggedProcess, pid int) (int, error) { if status.Exited() && wpid == dbp.Pid { dbp.exited = true - return -1, ProcessExitedError{Pid: wpid, Status: status.ExitStatus()} + return nil, ProcessExitedError{Pid: wpid, Status: status.ExitStatus()} } if status.StopSignal() == sys.SIGTRAP && status.TrapCause() == sys.PTRACE_EVENT_CLONE { // A traced thread has cloned a new thread, grab the pid and // add it to our list of traced threads. cloned, err := sys.PtraceGetEventMsg(wpid) if err != nil { - return -1, fmt.Errorf("could not get event message: %s", err) + return nil, fmt.Errorf("could not get event message: %s", err) } th, err := dbp.addThread(int(cloned), false) if err != nil { - return -1, err + return nil, err } err = th.Continue() if err != nil { - return -1, fmt.Errorf("could not continue new thread %d %s", cloned, err) + return nil, fmt.Errorf("could not continue new thread %d %s", cloned, err) } err = dbp.Threads[int(wpid)].Continue() if err != nil { - return -1, fmt.Errorf("could not continue new thread %d %s", cloned, err) + return nil, fmt.Errorf("could not continue new thread %d %s", cloned, err) } continue } if status.StopSignal() == sys.SIGTRAP { - return wpid, nil + thread, ok := dbp.Threads[wpid] + if !ok { + return nil, fmt.Errorf("could not find thread for %d", wpid) + } + return thread, nil } if status.StopSignal() == sys.SIGSTOP && dbp.halt { - return -1, ManualStopError{} + return nil, ManualStopError{} } } } -- GitLab