proc/native: race between RequestManualStop and trapWait

RequestManualStop will run concurrently with trapWait, since one writes
dbp.halt and the other reads it dbp.halt should be protected by a
mutex.

Updates #830
This commit is contained in:
aarzilli 2017-06-06 16:49:52 +02:00 committed by Alessandro Arzilli
parent 640dedb479
commit 98142c695b
3 changed files with 15 additions and 3 deletions

@ -37,6 +37,7 @@ type Process struct {
breakpointIDCounter int
internalBreakpointIDCounter int
firstStart bool
haltMu sync.Mutex
halt bool
exited bool
ptraceChan chan func()
@ -187,6 +188,8 @@ func (dbp *Process) RequestManualStop() error {
if dbp.exited {
return &proc.ProcessExitedError{}
}
dbp.haltMu.Lock()
defer dbp.haltMu.Unlock()
dbp.halt = true
return dbp.requestManualStop()
}

@ -291,7 +291,10 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
return nil, proc.ProcessExitedError{Pid: dbp.pid, Status: status.ExitStatus()}
case C.MACH_RCV_INTERRUPTED:
if !dbp.halt {
dbp.haltMu.Lock()
halt := dbp.halt
dbp.haltMu.Unlock()
if !halt {
// Call trapWait again, it seems
// MACH_RCV_INTERRUPTED is emitted before
// process natural death _sometimes_.
@ -319,7 +322,10 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
dbp.updateThreadList()
th, ok := dbp.threads[int(port)]
if !ok {
if dbp.halt {
dbp.haltMu.Lock()
halt := dbp.halt
dbp.haltMu.Unlock()
if halt {
dbp.halt = false
return th, nil
}

@ -236,7 +236,10 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
// Sometimes we get an unknown thread, ignore it?
continue
}
if status.StopSignal() == sys.SIGTRAP && dbp.halt {
dbp.haltMu.Lock()
halt := dbp.halt
dbp.haltMu.Unlock()
if status.StopSignal() == sys.SIGTRAP && halt {
th.running = false
dbp.halt = false
return th, nil