mirror of
https://github.com/go-delve/delve.git
synced 2025-10-29 09:46:56 +08:00
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:
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)))
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user