diff --git a/pkg/proc/native/proc.go b/pkg/proc/native/proc.go index 33bac079..d6c2d7bd 100644 --- a/pkg/proc/native/proc.go +++ b/pkg/proc/native/proc.go @@ -32,8 +32,7 @@ type Process struct { allGCache []*proc.G os *OSProcessDetails firstStart bool - haltMu sync.Mutex - halt bool + stopMu sync.Mutex resumeChan chan<- struct{} exited bool ptraceChan chan func() @@ -176,18 +175,17 @@ func (dbp *Process) RequestManualStop() error { if dbp.exited { return &proc.ProcessExitedError{Pid: dbp.Pid()} } - dbp.haltMu.Lock() - defer dbp.haltMu.Unlock() + dbp.stopMu.Lock() + defer dbp.stopMu.Unlock() dbp.manualStopRequested = true - dbp.halt = true return dbp.requestManualStop() } func (dbp *Process) CheckAndClearManualStopRequest() bool { - dbp.haltMu.Lock() + dbp.stopMu.Lock() msr := dbp.manualStopRequested dbp.manualStopRequested = false - dbp.haltMu.Unlock() + dbp.stopMu.Unlock() return msr } diff --git a/pkg/proc/native/proc_darwin.go b/pkg/proc/native/proc_darwin.go index 7fdd2892..0e08c6b0 100644 --- a/pkg/proc/native/proc_darwin.go +++ b/pkg/proc/native/proc_darwin.go @@ -25,6 +25,7 @@ type OSProcessDetails struct { exceptionPort C.mach_port_t // mach port for receiving mach exceptions. notificationPort C.mach_port_t // mach port for dead name notification (process exit). initialized bool + halt bool // the main port we use, will return messages from both the // exception and notification ports. @@ -191,6 +192,7 @@ func (dbp *Process) requestManualStop() (err error) { thread = C.mach_port_t(dbp.currentThread.os.threadAct) exceptionPort = C.mach_port_t(dbp.os.exceptionPort) ) + dbp.os.halt = true kret := C.raise_exception(task, thread, exceptionPort, C.EXC_BREAKPOINT) if kret != C.KERN_SUCCESS { return fmt.Errorf("could not raise mach exception") @@ -306,9 +308,9 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { return nil, proc.ProcessExitedError{Pid: dbp.pid, Status: status.ExitStatus()} case C.MACH_RCV_INTERRUPTED: - dbp.haltMu.Lock() - halt := dbp.halt - dbp.haltMu.Unlock() + dbp.stopMu.Lock() + halt := dbp.os.halt + dbp.stopMu.Unlock() if !halt { // Call trapWait again, it seems // MACH_RCV_INTERRUPTED is emitted before @@ -337,11 +339,11 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { dbp.updateThreadList() th, ok := dbp.threads[int(port)] if !ok { - dbp.haltMu.Lock() - halt := dbp.halt - dbp.haltMu.Unlock() + dbp.stopMu.Lock() + halt := dbp.os.halt + dbp.stopMu.Unlock() if halt { - dbp.halt = false + dbp.os.halt = false return th, nil } if dbp.firstStart || th.singleStepping { @@ -424,14 +426,14 @@ func (dbp *Process) resume() error { return nil } -// stop stops all running threads threads and sets breakpoints +// stop stops all running threads and sets breakpoints func (dbp *Process) stop(trapthread *Thread) (err error) { if dbp.exited { return &proc.ProcessExitedError{Pid: dbp.Pid()} } for _, th := range dbp.threads { if !th.Stopped() { - if err := th.halt(); err != nil { + if err := th.stop(); err != nil { return dbp.exitGuard(err) } } diff --git a/pkg/proc/native/proc_linux.go b/pkg/proc/native/proc_linux.go index 6362e4be..b88f505e 100644 --- a/pkg/proc/native/proc_linux.go +++ b/pkg/proc/native/proc_linux.go @@ -194,6 +194,10 @@ func findExecutable(path string, pid int) string { } func (dbp *Process) trapWait(pid int) (*Thread, error) { + return dbp.trapWaitInternal(pid, false) +} + +func (dbp *Process) trapWaitInternal(pid int, halt bool) (*Thread, error) { for { wpid, status, err := dbp.wait(pid, 0) if err != nil { @@ -235,11 +239,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { } return nil, err } - dbp.haltMu.Lock() - halt := dbp.halt - dbp.haltMu.Unlock() if halt { - dbp.halt = false th.os.running = false dbp.threads[int(wpid)].os.running = false return nil, nil @@ -263,15 +263,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { // Sometimes we get an unknown thread, ignore it? continue } - dbp.haltMu.Lock() - halt := dbp.halt - dbp.haltMu.Unlock() - if halt && (status.StopSignal() == sys.SIGTRAP || status.StopSignal() == sys.SIGSTOP) { - th.os.running = false - dbp.halt = false - return th, nil - } - if status.StopSignal() == sys.SIGTRAP { + if (halt && status.StopSignal() == sys.SIGSTOP) || (status.StopSignal() == sys.SIGTRAP) { th.os.running = false return th, nil } @@ -382,7 +374,7 @@ func (dbp *Process) exitGuard(err error) error { return err } if status(dbp.pid, dbp.os.comm) == StatusZombie { - _, err := dbp.trapWait(-1) + _, err := dbp.trapWaitInternal(-1, false) return err } @@ -415,7 +407,7 @@ func (dbp *Process) stop(trapthread *Thread) (err error) { } for _, th := range dbp.threads { if !th.Stopped() { - if err := th.halt(); err != nil { + if err := th.stop(); err != nil { return dbp.exitGuard(err) } } @@ -433,8 +425,7 @@ func (dbp *Process) stop(trapthread *Thread) (err error) { if allstopped { break } - dbp.halt = true - _, err := dbp.trapWait(-1) + _, err := dbp.trapWaitInternal(-1, true) if err != nil { return err } diff --git a/pkg/proc/native/threads_darwin.go b/pkg/proc/native/threads_darwin.go index 0589ce88..7edd444a 100644 --- a/pkg/proc/native/threads_darwin.go +++ b/pkg/proc/native/threads_darwin.go @@ -27,7 +27,7 @@ type OSSpecificDetails struct { // be continued. var ErrContinueThread = fmt.Errorf("could not continue thread") -func (t *Thread) halt() (err error) { +func (t *Thread) stop() (err error) { kret := C.thread_suspend(t.os.threadAct) if kret != C.KERN_SUCCESS { errStr := C.GoString(C.mach_error_string(C.mach_error_t(kret))) diff --git a/pkg/proc/native/threads_linux.go b/pkg/proc/native/threads_linux.go index fe6ce538..96defa43 100644 --- a/pkg/proc/native/threads_linux.go +++ b/pkg/proc/native/threads_linux.go @@ -17,10 +17,10 @@ type OSSpecificDetails struct { running bool } -func (t *Thread) halt() (err error) { +func (t *Thread) stop() (err error) { err = sys.Tgkill(t.dbp.pid, t.ID, sys.SIGSTOP) if err != nil { - err = fmt.Errorf("halt err %s on thread %d", err, t.ID) + err = fmt.Errorf("stop err %s on thread %d", err, t.ID) return } return