proc/native: move halt to os specific struct

The windows backend isn't using the halt field so it can be removed
there.
On linux it can be replaced with a parameter passed to trapWait.
This commit is contained in:
aarzilli
2018-02-14 10:53:01 +01:00
committed by Derek Parker
parent 8561db8c2c
commit 6c973bf230
5 changed files with 27 additions and 36 deletions

View File

@ -32,8 +32,7 @@ type Process struct {
allGCache []*proc.G allGCache []*proc.G
os *OSProcessDetails os *OSProcessDetails
firstStart bool firstStart bool
haltMu sync.Mutex stopMu sync.Mutex
halt bool
resumeChan chan<- struct{} resumeChan chan<- struct{}
exited bool exited bool
ptraceChan chan func() ptraceChan chan func()
@ -176,18 +175,17 @@ func (dbp *Process) RequestManualStop() error {
if dbp.exited { if dbp.exited {
return &proc.ProcessExitedError{Pid: dbp.Pid()} return &proc.ProcessExitedError{Pid: dbp.Pid()}
} }
dbp.haltMu.Lock() dbp.stopMu.Lock()
defer dbp.haltMu.Unlock() defer dbp.stopMu.Unlock()
dbp.manualStopRequested = true dbp.manualStopRequested = true
dbp.halt = true
return dbp.requestManualStop() return dbp.requestManualStop()
} }
func (dbp *Process) CheckAndClearManualStopRequest() bool { func (dbp *Process) CheckAndClearManualStopRequest() bool {
dbp.haltMu.Lock() dbp.stopMu.Lock()
msr := dbp.manualStopRequested msr := dbp.manualStopRequested
dbp.manualStopRequested = false dbp.manualStopRequested = false
dbp.haltMu.Unlock() dbp.stopMu.Unlock()
return msr return msr
} }

View File

@ -25,6 +25,7 @@ type OSProcessDetails struct {
exceptionPort C.mach_port_t // mach port for receiving mach exceptions. exceptionPort C.mach_port_t // mach port for receiving mach exceptions.
notificationPort C.mach_port_t // mach port for dead name notification (process exit). notificationPort C.mach_port_t // mach port for dead name notification (process exit).
initialized bool initialized bool
halt bool
// the main port we use, will return messages from both the // the main port we use, will return messages from both the
// exception and notification ports. // exception and notification ports.
@ -191,6 +192,7 @@ func (dbp *Process) requestManualStop() (err error) {
thread = C.mach_port_t(dbp.currentThread.os.threadAct) thread = C.mach_port_t(dbp.currentThread.os.threadAct)
exceptionPort = C.mach_port_t(dbp.os.exceptionPort) exceptionPort = C.mach_port_t(dbp.os.exceptionPort)
) )
dbp.os.halt = true
kret := C.raise_exception(task, thread, exceptionPort, C.EXC_BREAKPOINT) kret := C.raise_exception(task, thread, exceptionPort, C.EXC_BREAKPOINT)
if kret != C.KERN_SUCCESS { if kret != C.KERN_SUCCESS {
return fmt.Errorf("could not raise mach exception") 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()} return nil, proc.ProcessExitedError{Pid: dbp.pid, Status: status.ExitStatus()}
case C.MACH_RCV_INTERRUPTED: case C.MACH_RCV_INTERRUPTED:
dbp.haltMu.Lock() dbp.stopMu.Lock()
halt := dbp.halt halt := dbp.os.halt
dbp.haltMu.Unlock() dbp.stopMu.Unlock()
if !halt { if !halt {
// Call trapWait again, it seems // Call trapWait again, it seems
// MACH_RCV_INTERRUPTED is emitted before // MACH_RCV_INTERRUPTED is emitted before
@ -337,11 +339,11 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
dbp.updateThreadList() dbp.updateThreadList()
th, ok := dbp.threads[int(port)] th, ok := dbp.threads[int(port)]
if !ok { if !ok {
dbp.haltMu.Lock() dbp.stopMu.Lock()
halt := dbp.halt halt := dbp.os.halt
dbp.haltMu.Unlock() dbp.stopMu.Unlock()
if halt { if halt {
dbp.halt = false dbp.os.halt = false
return th, nil return th, nil
} }
if dbp.firstStart || th.singleStepping { if dbp.firstStart || th.singleStepping {
@ -424,14 +426,14 @@ func (dbp *Process) resume() error {
return nil 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) { func (dbp *Process) stop(trapthread *Thread) (err error) {
if dbp.exited { if dbp.exited {
return &proc.ProcessExitedError{Pid: dbp.Pid()} return &proc.ProcessExitedError{Pid: dbp.Pid()}
} }
for _, th := range dbp.threads { for _, th := range dbp.threads {
if !th.Stopped() { if !th.Stopped() {
if err := th.halt(); err != nil { if err := th.stop(); err != nil {
return dbp.exitGuard(err) return dbp.exitGuard(err)
} }
} }

View File

@ -194,6 +194,10 @@ func findExecutable(path string, pid int) string {
} }
func (dbp *Process) trapWait(pid int) (*Thread, error) { func (dbp *Process) trapWait(pid int) (*Thread, error) {
return dbp.trapWaitInternal(pid, false)
}
func (dbp *Process) trapWaitInternal(pid int, halt bool) (*Thread, error) {
for { for {
wpid, status, err := dbp.wait(pid, 0) wpid, status, err := dbp.wait(pid, 0)
if err != nil { if err != nil {
@ -235,11 +239,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
} }
return nil, err return nil, err
} }
dbp.haltMu.Lock()
halt := dbp.halt
dbp.haltMu.Unlock()
if halt { if halt {
dbp.halt = false
th.os.running = false th.os.running = false
dbp.threads[int(wpid)].os.running = false dbp.threads[int(wpid)].os.running = false
return nil, nil return nil, nil
@ -263,15 +263,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
// Sometimes we get an unknown thread, ignore it? // Sometimes we get an unknown thread, ignore it?
continue continue
} }
dbp.haltMu.Lock() if (halt && status.StopSignal() == sys.SIGSTOP) || (status.StopSignal() == sys.SIGTRAP) {
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 {
th.os.running = false th.os.running = false
return th, nil return th, nil
} }
@ -382,7 +374,7 @@ func (dbp *Process) exitGuard(err error) error {
return err return err
} }
if status(dbp.pid, dbp.os.comm) == StatusZombie { if status(dbp.pid, dbp.os.comm) == StatusZombie {
_, err := dbp.trapWait(-1) _, err := dbp.trapWaitInternal(-1, false)
return err return err
} }
@ -415,7 +407,7 @@ func (dbp *Process) stop(trapthread *Thread) (err error) {
} }
for _, th := range dbp.threads { for _, th := range dbp.threads {
if !th.Stopped() { if !th.Stopped() {
if err := th.halt(); err != nil { if err := th.stop(); err != nil {
return dbp.exitGuard(err) return dbp.exitGuard(err)
} }
} }
@ -433,8 +425,7 @@ func (dbp *Process) stop(trapthread *Thread) (err error) {
if allstopped { if allstopped {
break break
} }
dbp.halt = true _, err := dbp.trapWaitInternal(-1, true)
_, err := dbp.trapWait(-1)
if err != nil { if err != nil {
return err return err
} }

View File

@ -27,7 +27,7 @@ type OSSpecificDetails struct {
// be continued. // be continued.
var ErrContinueThread = fmt.Errorf("could not continue thread") 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) kret := C.thread_suspend(t.os.threadAct)
if kret != C.KERN_SUCCESS { if kret != C.KERN_SUCCESS {
errStr := C.GoString(C.mach_error_string(C.mach_error_t(kret))) errStr := C.GoString(C.mach_error_string(C.mach_error_t(kret)))

View File

@ -17,10 +17,10 @@ type OSSpecificDetails struct {
running bool running bool
} }
func (t *Thread) halt() (err error) { func (t *Thread) stop() (err error) {
err = sys.Tgkill(t.dbp.pid, t.ID, sys.SIGSTOP) err = sys.Tgkill(t.dbp.pid, t.ID, sys.SIGSTOP)
if err != nil { 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
} }
return return