github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/runtime/testdata/testprogcgo/exec.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build !plan9,!windows 6 7 package main 8 9 /* 10 #include <stddef.h> 11 #include <signal.h> 12 #include <pthread.h> 13 14 // Save the signal mask at startup so that we see what it is before 15 // the Go runtime starts setting up signals. 16 17 static sigset_t mask; 18 19 static void init(void) __attribute__ ((constructor)); 20 21 static void init() { 22 sigemptyset(&mask); 23 pthread_sigmask(SIG_SETMASK, NULL, &mask); 24 } 25 26 int SIGINTBlocked() { 27 return sigismember(&mask, SIGINT); 28 } 29 */ 30 import "C" 31 32 import ( 33 "fmt" 34 "io/fs" 35 "os" 36 "os/exec" 37 "os/signal" 38 "sync" 39 "syscall" 40 ) 41 42 func init() { 43 register("CgoExecSignalMask", CgoExecSignalMask) 44 } 45 46 func CgoExecSignalMask() { 47 if len(os.Args) > 2 && os.Args[2] == "testsigint" { 48 if C.SIGINTBlocked() != 0 { 49 os.Exit(1) 50 } 51 os.Exit(0) 52 } 53 54 c := make(chan os.Signal, 1) 55 signal.Notify(c, syscall.SIGTERM) 56 go func() { 57 for range c { 58 } 59 }() 60 61 const goCount = 10 62 const execCount = 10 63 var wg sync.WaitGroup 64 wg.Add(goCount*execCount + goCount) 65 for i := 0; i < goCount; i++ { 66 go func() { 67 defer wg.Done() 68 for j := 0; j < execCount; j++ { 69 c2 := make(chan os.Signal, 1) 70 signal.Notify(c2, syscall.SIGUSR1) 71 syscall.Kill(os.Getpid(), syscall.SIGTERM) 72 go func(j int) { 73 defer wg.Done() 74 cmd := exec.Command(os.Args[0], "CgoExecSignalMask", "testsigint") 75 cmd.Stdin = os.Stdin 76 cmd.Stdout = os.Stdout 77 cmd.Stderr = os.Stderr 78 if err := cmd.Run(); err != nil { 79 // An overloaded system 80 // may fail with EAGAIN. 81 // This doesn't tell us 82 // anything useful; ignore it. 83 // Issue #27731. 84 if isEAGAIN(err) { 85 return 86 } 87 fmt.Printf("iteration %d: %v\n", j, err) 88 os.Exit(1) 89 } 90 }(j) 91 signal.Stop(c2) 92 } 93 }() 94 } 95 wg.Wait() 96 97 fmt.Println("OK") 98 } 99 100 // isEAGAIN reports whether err is an EAGAIN error from a process execution. 101 func isEAGAIN(err error) bool { 102 if p, ok := err.(*fs.PathError); ok { 103 err = p.Err 104 } 105 return err == syscall.EAGAIN 106 }