Fix Linux panic

This commit is contained in:
Derek Parker 2015-02-27 22:35:26 -05:00
parent 450e5c4805
commit 27f68abebd
3 changed files with 17 additions and 33 deletions

@ -5,9 +5,10 @@ import (
"debug/gosym" "debug/gosym"
"fmt" "fmt"
"os" "os"
"path/filepath"
"strconv"
"sync" "sync"
"syscall" "syscall"
"time"
sys "golang.org/x/sys/unix" sys "golang.org/x/sys/unix"
@ -103,20 +104,22 @@ func (dbp *DebuggedProcess) addThread(tid int, attach bool) (*ThreadContext, err
Process: dbp, Process: dbp,
} }
if dbp.CurrentThread == nil {
dbp.CurrentThread = dbp.Threads[tid]
}
return dbp.Threads[tid], nil return dbp.Threads[tid], nil
} }
func (dbp *DebuggedProcess) updateThreadList() error { func (dbp *DebuggedProcess) updateThreadList() error {
allm, err := dbp.CurrentThread.AllM() tids, _ := filepath.Glob(fmt.Sprintf("/proc/%d/task/*", dbp.Pid))
if err != nil { for _, tidpath := range tids {
return err tidstr := filepath.Base(tidpath)
} tid, err := strconv.Atoi(tidstr)
// TODO(dp) user /proc/<pid>/task to remove reliance on allm if err != nil {
for _, m := range allm { return err
if m.procid == 0 {
continue
} }
if _, err := dbp.addThread(m.procid, false); err != nil { if _, err := dbp.addThread(tid, false); err != nil {
return err 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) 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 return dbp.Threads[cloner].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)
}
} }
func stopped(pid int) bool { func stopped(pid int) bool {

@ -107,7 +107,7 @@ func TestBreakPoint(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if pc-1 != bp.Addr { if pc-1 != bp.Addr && pc != bp.Addr {
f, l, _ := p.GoSymTable.PCToLine(pc) f, l, _ := p.GoSymTable.PCToLine(pc)
t.Fatalf("Break not respected:\nPC:%#v %s:%d\nFN:%#v \n", pc, f, l, bp.Addr) t.Fatalf("Break not respected:\nPC:%#v %s:%d\nFN:%#v \n", pc, f, l, bp.Addr)
} }

@ -18,13 +18,14 @@ func (t *ThreadContext) Halt() error {
if err != nil { if err != nil {
return fmt.Errorf("Halt err %s %d", err, t.Id) return fmt.Errorf("Halt err %s %d", err, t.Id)
} }
_, _, err = wait(t.Id, sys.WNOHANG) _, _, err = wait(t.Id, 0)
if err != nil { if err != nil {
return fmt.Errorf("wait err %s %d", err, t.Id) return fmt.Errorf("wait err %s %d", err, t.Id)
} }
return nil return nil
} }
// TODO(dp) rename this to resume or something
func (t *ThreadContext) cont() error { func (t *ThreadContext) cont() error {
return PtraceCont(t.Id, 0) return PtraceCont(t.Id, 0)
} }