Return thread directly from trapWait
This commit is contained in:
parent
c6d9b0e63c
commit
e7a9daf248
@ -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 dbp.CurrentThread != thread {
|
||||
dbp.SwitchThread(thread.Id)
|
||||
}
|
||||
|
||||
if wpid != dbp.CurrentThread.Id {
|
||||
dbp.SwitchThread(wpid)
|
||||
}
|
||||
|
||||
pc, err := thread.CurrentPC()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -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) {
|
||||
|
@ -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{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user