diff --git a/proctl/proctl_linux.go b/proctl/proctl_linux.go index c7681f6b..a0235ae7 100644 --- a/proctl/proctl_linux.go +++ b/proctl/proctl_linux.go @@ -5,9 +5,10 @@ import ( "debug/gosym" "fmt" "os" + "path/filepath" + "strconv" "sync" "syscall" - "time" sys "golang.org/x/sys/unix" @@ -103,20 +104,22 @@ func (dbp *DebuggedProcess) addThread(tid int, attach bool) (*ThreadContext, err Process: dbp, } + if dbp.CurrentThread == nil { + dbp.CurrentThread = dbp.Threads[tid] + } + return dbp.Threads[tid], nil } func (dbp *DebuggedProcess) updateThreadList() error { - allm, err := dbp.CurrentThread.AllM() - if err != nil { - return err - } - // TODO(dp) user /proc//task to remove reliance on allm - for _, m := range allm { - if m.procid == 0 { - continue + tids, _ := filepath.Glob(fmt.Sprintf("/proc/%d/task/*", dbp.Pid)) + for _, tidpath := range tids { + tidstr := filepath.Base(tidpath) + tid, err := strconv.Atoi(tidstr) + if err != nil { + return err } - if _, err := dbp.addThread(m.procid, false); err != nil { + if _, err := dbp.addThread(tid, false); err != nil { return err } } @@ -210,27 +213,7 @@ func addNewThread(dbp *DebuggedProcess, cloner, cloned int) error { return fmt.Errorf("could not continue new thread %d %s", cloned, err) } - // Here we loop for a while to ensure that the once we continue - // the newly created thread, we allow enough time for the runtime - // to assign m->procid. This is important because we rely on - // looping through runtime.allm in other parts of the code, so - // we require that this is set before we do anything else. - // TODO(dp): we might be able to eliminate this loop by telling - // the CPU to emit a breakpoint exception on write to this location - // in memory. That way we prevent having to loop, and can be - // notified as soon as m->procid is set. - // TODO(dp) get rid of this hack - th = dbp.Threads[cloner] - for { - allm, _ := th.AllM() - for _, m := range allm { - if m.procid == cloned { - // Continue the thread that cloned - return th.Continue() - } - } - time.Sleep(time.Millisecond) - } + return dbp.Threads[cloner].Continue() } func stopped(pid int) bool { diff --git a/proctl/proctl_test.go b/proctl/proctl_test.go index 2b74885e..948ea22a 100644 --- a/proctl/proctl_test.go +++ b/proctl/proctl_test.go @@ -107,7 +107,7 @@ func TestBreakPoint(t *testing.T) { t.Fatal(err) } - if pc-1 != bp.Addr { + if pc-1 != bp.Addr && pc != bp.Addr { f, l, _ := p.GoSymTable.PCToLine(pc) t.Fatalf("Break not respected:\nPC:%#v %s:%d\nFN:%#v \n", pc, f, l, bp.Addr) } diff --git a/proctl/threads_linux.go b/proctl/threads_linux.go index bfaf676d..a7272c34 100644 --- a/proctl/threads_linux.go +++ b/proctl/threads_linux.go @@ -18,13 +18,14 @@ func (t *ThreadContext) Halt() error { if err != nil { return fmt.Errorf("Halt err %s %d", err, t.Id) } - _, _, err = wait(t.Id, sys.WNOHANG) + _, _, err = wait(t.Id, 0) if err != nil { return fmt.Errorf("wait err %s %d", err, t.Id) } return nil } +// TODO(dp) rename this to resume or something func (t *ThreadContext) cont() error { return PtraceCont(t.Id, 0) }