fix(debug): handle mapping edges, stray traps and dying debuggees
Assisted-by: GLM 5.3
This commit is contained in:
@@ -97,6 +97,16 @@ func LaunchWithBuffers(gasmBin, asmPath, funcName string, args []byte, bufSpec s
|
||||
if _, err := os.Stat(readyFile); err == nil {
|
||||
break
|
||||
}
|
||||
// A debuggee that died before signalling readiness (unknown
|
||||
// function, unparseable source) writes its failure notice to the
|
||||
// handshake directory; read it and fail fast. The poll never
|
||||
// waits on the child: a wait here could consume the SIGSTOP park
|
||||
// that waitStopped below must receive, hanging the launch.
|
||||
if err := s.deadReason(); err != nil {
|
||||
cmd.Wait()
|
||||
os.RemoveAll(tmpDir)
|
||||
return nil, nil, err
|
||||
}
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
}
|
||||
|
||||
@@ -134,6 +144,18 @@ func LaunchWithBuffers(gasmBin, asmPath, funcName string, args []byte, bufSpec s
|
||||
return s, bufAddrs, nil
|
||||
}
|
||||
|
||||
// deadReason reports the debuggee's own failure notice, the file its
|
||||
// failure paths write before exiting. A debuggee killed without a notice
|
||||
// (a crash, SIGKILL) surfaces through waitStopped after the poll instead,
|
||||
// which is why the poll's budget stays finite.
|
||||
func (s *Session) deadReason() error {
|
||||
data, err := os.ReadFile(filepath.Join(s.tmpDir, "dead"))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("debug: debuggee failed before signalling readiness: %s", strings.TrimSpace(string(data)))
|
||||
}
|
||||
|
||||
// waitStopped consumes ptrace-stop events until one the debugger cares
|
||||
// about arrives: SIGTRAP (a breakpoint or a completed single-step), the
|
||||
// debuggee's own SIGSTOP, or a genuine signal-delivery-stop. A Go tracee's
|
||||
|
||||
Reference in New Issue
Block a user