mirror of
				https://github.com/go-delve/delve.git
				synced 2025-10-31 02:36:18 +08:00 
			
		
		
		
	 bd2a4fe56e
			
		
	
	bd2a4fe56e
	
	
	
		
			
			Handle the signaled status for the thread leader like we handle the exited status, by returning ErrProcessExited and recording the killer signal in it. Prior to this commit we would find out about the death of the thread later in the loop, the condition would still be reported as ErrProcessExited, but without recording the signal number anywhere. Also fixes a bug in TestAttachStopOnEntry where the test would inadvertently cause a SIGPIPE to be sent to the target process, making it terminate early.
		
			
				
	
	
		
			103 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			103 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // +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, fixture protest.Fixture) {
 | |
| 		defer close(errChan)
 | |
| 		setFunctionBreakpoint(p, t, "main.main")
 | |
| 		assertNoError(p.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
 | |
| 				p.RequestManualStop()
 | |
| 				err := p.Detach(true)
 | |
| 				errChan <- errIssue419{pid: p.Pid(), err: err}
 | |
| 				return
 | |
| 			}
 | |
| 			err := syscall.Kill(p.Pid(), syscall.SIGINT)
 | |
| 			errChan <- errIssue419{pid: p.Pid(), err: err}
 | |
| 		}()
 | |
| 		p.ResumeNotify(resumeChan)
 | |
| 		errChan <- p.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)
 | |
| 	}
 | |
| }
 |