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