delve/pkg/proc/proc_unix_test.go
Alessandro Arzilli 37e44bf603
proc,proc/native: adds ability to automatically debug child processes (#3165)
Adds the ability to automatically debug child processes executed by the
target to the linux native backend.
This commit does not contain user interface or API to access this
functionality.

Updates #2551
2023-02-22 09:26:28 -08:00

103 lines
2.5 KiB
Go

//go:build linux || darwin
// +build linux darwin
package proc_test
import (
"fmt"
"os"
"os/exec"
"runtime"
"syscall"
"testing"
"time"
"golang.org/x/sys/unix"
"github.com/go-delve/delve/pkg/proc"
"github.com/go-delve/delve/pkg/proc/native"
protest "github.com/go-delve/delve/pkg/proc/test"
)
type errIssue419 struct {
pid int
err error
}
func (npe errIssue419) Error() string {
return fmt.Sprintf("Pid is zero or negative: %d", npe.pid)
}
func TestIssue419(t *testing.T) {
if testBackend == "rr" {
return
}
errChan := make(chan error, 2)
// SIGINT directed at the inferior should be passed along not swallowed by delve
withTestProcess("issue419", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) {
setFunctionBreakpoint(p, t, "main.main")
assertNoError(grp.Continue(), t, "Continue()")
resumeChan := make(chan struct{}, 1)
go func() {
time.Sleep(500 * time.Millisecond)
<-resumeChan
if p.Pid() <= 0 {
// if we don't stop the inferior the test will never finish
grp.RequestManualStop()
err := grp.Detach(true)
errChan <- errIssue419{pid: p.Pid(), err: err}
return
}
err := syscall.Kill(p.Pid(), syscall.SIGINT)
errChan <- errIssue419{pid: p.Pid(), err: err}
}()
grp.ResumeNotify(resumeChan)
errChan <- grp.Continue()
})
for i := 0; i < 2; i++ {
err := <-errChan
t.Logf("error %T %#v\n", err, err)
if v, ok := err.(errIssue419); ok {
assertNoError(v.err, t, "syscall.Kill")
continue
}
if _, exited := err.(proc.ErrProcessExited); !exited {
t.Fatalf("Unexpected error after Continue(): %v\n", err)
}
}
}
func TestSignalDeath(t *testing.T) {
if testBackend != "native" || runtime.GOOS != "linux" {
t.Skip("skipped on non-linux non-native backends")
}
var buildFlags protest.BuildFlags
if buildMode == "pie" {
buildFlags |= protest.BuildModePIE
}
fixture := protest.BuildFixture("loopprog", buildFlags)
cmd := exec.Command(fixture.Path)
stdout, err := cmd.StdoutPipe()
assertNoError(err, t, "StdoutPipe")
cmd.Stderr = os.Stderr
assertNoError(cmd.Start(), t, "starting fixture")
p, err := native.Attach(cmd.Process.Pid, []string{})
assertNoError(err, t, "Attach")
stdout.Close() // target will receive SIGPIPE later on
err = p.Continue()
t.Logf("error is %v", err)
exitErr, isexited := err.(proc.ErrProcessExited)
if !isexited {
t.Fatal("did not exit")
}
if exitErr.Status != -int(unix.SIGPIPE) {
t.Fatalf("expected SIGPIPE got %d\n", exitErr.Status)
}
}