proc: move breakpoint condition evaluation out of backends (#2628)

* proc: move breakpoint condition evaluation out of backends

Moves breakpoint condition evaluation from the point where breakpoints
are set, inside ContinueOnce, to (*Target).Continue.

This accomplishes three things:

1. the breakpoint evaluation method needs not be exported anymore
2. breakpoint condition evaluation can be done with a full scope,
   containing a Target object, something that wasn't possible before
   because ContinueOnce doesn't have access to the Target object.
3. moves breakpoint condition evaluation out of the critical section
   where some of the threads of the target process might be still
   running.

* proc/native: handle process death during stop() on Windows

It is possible that the thread dies while we are inside the stop()
function. This results in an Access is denied error being returned by
SuspendThread being called on threads that no longer exist.

Delay the reporting the error from SuspendThread until the end of
stop() and only report it if the thread still exists at that point.

Fixes flakyness with TestIssue1101 that was exacerbated by moving
breakpoint condition evaluation outside of the backends.
This commit is contained in:
Alessandro Arzilli
2021-08-09 19:16:24 +02:00
committed by GitHub
parent 4e5bddee9b
commit f3e76238e3
15 changed files with 117 additions and 55 deletions

View File

@ -581,8 +581,8 @@ func (err *IsNilErr) Error() string {
return fmt.Sprintf("%s is nil", err.name)
}
func globalScope(bi *BinaryInfo, image *Image, mem MemoryReadWriter) *EvalScope {
return &EvalScope{Location: Location{}, Regs: op.DwarfRegisters{StaticBase: image.StaticBase}, Mem: mem, g: nil, BinInfo: bi, frameOffset: 0}
func globalScope(tgt *Target, bi *BinaryInfo, image *Image, mem MemoryReadWriter) *EvalScope {
return &EvalScope{Location: Location{}, Regs: op.DwarfRegisters{StaticBase: image.StaticBase}, Mem: mem, g: nil, BinInfo: bi, target: tgt, frameOffset: 0}
}
func newVariableFromThread(t Thread, name string, addr uint64, dwarfType godwarf.Type) *Variable {
@ -947,8 +947,8 @@ func (v *Variable) fieldVariable(name string) *Variable {
var errTracebackAncestorsDisabled = errors.New("tracebackancestors is disabled")
// Ancestors returns the list of ancestors for g.
func Ancestors(p Process, g *G, n int) ([]Ancestor, error) {
scope := globalScope(p.BinInfo(), p.BinInfo().Images[0], p.Memory())
func Ancestors(p *Target, g *G, n int) ([]Ancestor, error) {
scope := globalScope(p, p.BinInfo(), p.BinInfo().Images[0], p.Memory())
tbav, err := scope.EvalExpression("runtime.debug.tracebackancestors", loadSingleValue)
if err == nil && tbav.Unreadable == nil && tbav.Kind == reflect.Int {
tba, _ := constant.Int64Val(tbav.Value)