github.com/undoio/delve@v1.9.0/pkg/proc/proc_unix_test.go (about)

     1  //go:build linux || darwin
     2  // +build linux darwin
     3  
     4  package proc_test
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"os/exec"
    10  	"runtime"
    11  	"syscall"
    12  	"testing"
    13  	"time"
    14  
    15  	"golang.org/x/sys/unix"
    16  
    17  	"github.com/undoio/delve/pkg/proc"
    18  	"github.com/undoio/delve/pkg/proc/native"
    19  	protest "github.com/undoio/delve/pkg/proc/test"
    20  )
    21  
    22  type errIssue419 struct {
    23  	pid int
    24  	err error
    25  }
    26  
    27  func (npe errIssue419) Error() string {
    28  	return fmt.Sprintf("Pid is zero or negative: %d", npe.pid)
    29  }
    30  
    31  func TestIssue419(t *testing.T) {
    32  	if testBackend == "rr" || testBackend == "undo" {
    33  		return
    34  	}
    35  
    36  	errChan := make(chan error, 2)
    37  
    38  	// SIGINT directed at the inferior should be passed along not swallowed by delve
    39  	withTestProcess("issue419", t, func(p *proc.Target, fixture protest.Fixture) {
    40  		setFunctionBreakpoint(p, t, "main.main")
    41  		assertNoError(p.Continue(), t, "Continue()")
    42  		resumeChan := make(chan struct{}, 1)
    43  		go func() {
    44  			time.Sleep(500 * time.Millisecond)
    45  			<-resumeChan
    46  			if p.Pid() <= 0 {
    47  				// if we don't stop the inferior the test will never finish
    48  				p.RequestManualStop()
    49  				err := p.Detach(true)
    50  				errChan <- errIssue419{pid: p.Pid(), err: err}
    51  				return
    52  			}
    53  			err := syscall.Kill(p.Pid(), syscall.SIGINT)
    54  			errChan <- errIssue419{pid: p.Pid(), err: err}
    55  		}()
    56  		p.ResumeNotify(resumeChan)
    57  		errChan <- p.Continue()
    58  	})
    59  
    60  	for i := 0; i < 2; i++ {
    61  		err := <-errChan
    62  
    63  		t.Logf("error %T %#v\n", err, err)
    64  
    65  		if v, ok := err.(errIssue419); ok {
    66  			assertNoError(v.err, t, "syscall.Kill")
    67  			continue
    68  		}
    69  
    70  		if _, exited := err.(proc.ErrProcessExited); !exited {
    71  			t.Fatalf("Unexpected error after Continue(): %v\n", err)
    72  		}
    73  	}
    74  }
    75  
    76  func TestSignalDeath(t *testing.T) {
    77  	if testBackend != "native" || runtime.GOOS != "linux" {
    78  		t.Skip("skipped on non-linux non-native backends")
    79  	}
    80  	var buildFlags protest.BuildFlags
    81  	if buildMode == "pie" {
    82  		buildFlags |= protest.BuildModePIE
    83  	}
    84  	fixture := protest.BuildFixture("loopprog", buildFlags)
    85  	cmd := exec.Command(fixture.Path)
    86  	stdout, err := cmd.StdoutPipe()
    87  	assertNoError(err, t, "StdoutPipe")
    88  	cmd.Stderr = os.Stderr
    89  	assertNoError(cmd.Start(), t, "starting fixture")
    90  	p, err := native.Attach(cmd.Process.Pid, []string{})
    91  	assertNoError(err, t, "Attach")
    92  	stdout.Close() // target will receive SIGPIPE later on
    93  	err = p.Continue()
    94  	t.Logf("error is %v", err)
    95  	exitErr, isexited := err.(proc.ErrProcessExited)
    96  	if !isexited {
    97  		t.Fatal("did not exit")
    98  	}
    99  	if exitErr.Status != -int(unix.SIGPIPE) {
   100  		t.Fatalf("expected SIGPIPE got %d\n", exitErr.Status)
   101  	}
   102  }