Return thread directly from trapWait
This commit is contained in:
parent
c6d9b0e63c
commit
e7a9daf248
@ -279,32 +279,28 @@ func (dbp *DebuggedProcess) next() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
tid, err := trapWait(dbp, -1)
|
thread, err := trapWait(dbp, -1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
th, ok := dbp.Threads[tid]
|
pc, err := thread.CurrentPC()
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("unknown thread %d", tid)
|
|
||||||
}
|
|
||||||
pc, err := th.CurrentPC()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Check if we've hit a software breakpoint. If so, reset PC.
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
// Grab the current goroutine for this thread.
|
// Grab the current goroutine for this thread.
|
||||||
tg, err := th.curG()
|
tg, err := thread.curG()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Make sure we're on the same goroutine.
|
// Make sure we're on the same goroutine.
|
||||||
// TODO(dp) take into account goroutine exit.
|
// TODO(dp) take into account goroutine exit.
|
||||||
if tg.id == curg.id {
|
if tg.id == curg.id {
|
||||||
if dbp.CurrentThread.Id != tid {
|
if dbp.CurrentThread != thread {
|
||||||
dbp.SwitchThread(tid)
|
dbp.SwitchThread(thread.Id)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -322,20 +318,13 @@ func (dbp *DebuggedProcess) Continue() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn := func() error {
|
fn := func() error {
|
||||||
wpid, err := trapWait(dbp, -1)
|
thread, err := trapWait(dbp, -1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if dbp.CurrentThread != thread {
|
||||||
thread, ok := dbp.Threads[wpid]
|
dbp.SwitchThread(thread.Id)
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("could not find thread for %d", wpid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if wpid != dbp.CurrentThread.Id {
|
|
||||||
dbp.SwitchThread(wpid)
|
|
||||||
}
|
|
||||||
|
|
||||||
pc, err := thread.CurrentPC()
|
pc, err := thread.CurrentPC()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -171,17 +171,17 @@ func (dbp *DebuggedProcess) findExecutable() (*macho.File, error) {
|
|||||||
return exe, nil
|
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)
|
port := C.mach_port_wait(dbp.os.portSet)
|
||||||
|
|
||||||
switch port {
|
switch port {
|
||||||
case dbp.os.notificationPort:
|
case dbp.os.notificationPort:
|
||||||
_, status, err := wait(dbp.Pid, 0)
|
_, status, err := wait(dbp.Pid, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dbp.exited = true
|
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:
|
case C.MACH_RCV_INTERRUPTED:
|
||||||
if !dbp.halt {
|
if !dbp.halt {
|
||||||
// Call trapWait again, it seems
|
// Call trapWait again, it seems
|
||||||
@ -189,16 +189,19 @@ func trapWait(dbp *DebuggedProcess, pid int) (int, error) {
|
|||||||
// process natural death _sometimes_.
|
// process natural death _sometimes_.
|
||||||
return trapWait(dbp, pid)
|
return trapWait(dbp, pid)
|
||||||
}
|
}
|
||||||
return -1, ManualStopError{}
|
return nil, ManualStopError{}
|
||||||
case 0:
|
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
|
// Since we cannot be notified of new threads on OS X
|
||||||
// this is as good a time as any to check for them.
|
// this is as good a time as any to check for them.
|
||||||
dbp.updateThreadList()
|
dbp.updateThreadList()
|
||||||
|
thread, ok := dbp.Threads[int(port)]
|
||||||
return int(port), nil
|
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) {
|
func wait(pid, options int) (int, *sys.WaitStatus, error) {
|
||||||
|
@ -216,11 +216,11 @@ func stopped(pid int) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func trapWait(dbp *DebuggedProcess, pid int) (int, error) {
|
func trapWait(dbp *DebuggedProcess, pid int) (*ThreadContext, error) {
|
||||||
for {
|
for {
|
||||||
wpid, status, err := wait(pid, 0)
|
wpid, status, err := wait(pid, 0)
|
||||||
if err != nil {
|
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 {
|
if wpid == 0 {
|
||||||
continue
|
continue
|
||||||
@ -231,37 +231,41 @@ func trapWait(dbp *DebuggedProcess, pid int) (int, error) {
|
|||||||
|
|
||||||
if status.Exited() && wpid == dbp.Pid {
|
if status.Exited() && wpid == dbp.Pid {
|
||||||
dbp.exited = true
|
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 {
|
if status.StopSignal() == sys.SIGTRAP && status.TrapCause() == sys.PTRACE_EVENT_CLONE {
|
||||||
// A traced thread has cloned a new thread, grab the pid and
|
// A traced thread has cloned a new thread, grab the pid and
|
||||||
// add it to our list of traced threads.
|
// add it to our list of traced threads.
|
||||||
cloned, err := sys.PtraceGetEventMsg(wpid)
|
cloned, err := sys.PtraceGetEventMsg(wpid)
|
||||||
if err != nil {
|
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)
|
th, err := dbp.addThread(int(cloned), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = th.Continue()
|
err = th.Continue()
|
||||||
if err != nil {
|
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()
|
err = dbp.Threads[int(wpid)].Continue()
|
||||||
if err != nil {
|
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
|
continue
|
||||||
}
|
}
|
||||||
if status.StopSignal() == sys.SIGTRAP {
|
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 {
|
if status.StopSignal() == sys.SIGSTOP && dbp.halt {
|
||||||
return -1, ManualStopError{}
|
return nil, ManualStopError{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user