mirror of
https://github.com/golang/go
synced 2024-10-02 08:28:36 -06:00
runtime: set new m signal mask to program startup mask
We were setting the signal mask of a new m to the signal mask of the m that created it. That failed when that m happened to be the one created by ensureSigM, which sets its signal mask to only include the signals being caught by os/signal.Notify. Fixes #13164. Update #9896. Change-Id: I705c196fe9d11754e10bab9e9b2e7530ecdfa367 Reviewed-on: https://go-review.googlesource.com/18064 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
a7cad52e04
commit
70c9a8187a
@ -121,3 +121,16 @@ func TestCgoDLLImports(t *testing.T) {
|
||||
t.Fatalf("expected %q, but got %v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCgoExecSignalMask(t *testing.T) {
|
||||
// Test issue 13164.
|
||||
switch runtime.GOOS {
|
||||
case "windows", "plan9":
|
||||
t.Skipf("skipping signal mask test on %s", runtime.GOOS)
|
||||
}
|
||||
got := runTestProg(t, "testprogcgo", "CgoExecSignalMask")
|
||||
want := "OK\n"
|
||||
if got != want {
|
||||
t.Errorf("expected %q, got %v", want, got)
|
||||
}
|
||||
}
|
||||
|
@ -98,6 +98,9 @@ func main_main()
|
||||
// runtimeInitTime is the nanotime() at which the runtime started.
|
||||
var runtimeInitTime int64
|
||||
|
||||
// Value to use for signal mask for newly created M's.
|
||||
var initSigmask sigset
|
||||
|
||||
// The main goroutine.
|
||||
func main() {
|
||||
g := getg()
|
||||
@ -430,6 +433,9 @@ func schedinit() {
|
||||
mallocinit()
|
||||
mcommoninit(_g_.m)
|
||||
|
||||
msigsave(_g_.m)
|
||||
initSigmask = _g_.m.sigmask
|
||||
|
||||
goargs()
|
||||
goenvs()
|
||||
parsedebugvars()
|
||||
@ -1480,7 +1486,7 @@ func unlockextra(mp *m) {
|
||||
func newm(fn func(), _p_ *p) {
|
||||
mp := allocm(_p_, fn)
|
||||
mp.nextp.set(_p_)
|
||||
msigsave(mp)
|
||||
mp.sigmask = initSigmask
|
||||
if iscgo {
|
||||
var ts cgothreadstart
|
||||
if _cgo_thread_start == nil {
|
||||
|
89
src/runtime/testdata/testprogcgo/exec.go
vendored
Normal file
89
src/runtime/testdata/testprogcgo/exec.go
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !plan9,!windows
|
||||
|
||||
package main
|
||||
|
||||
/*
|
||||
#include <stddef.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
|
||||
// Save the signal mask at startup so that we see what it is before
|
||||
// the Go runtime starts setting up signals.
|
||||
|
||||
static sigset_t mask;
|
||||
|
||||
static void init(void) __attribute__ ((constructor));
|
||||
|
||||
static void init() {
|
||||
sigemptyset(&mask);
|
||||
pthread_sigmask(SIG_SETMASK, NULL, &mask);
|
||||
}
|
||||
|
||||
int SIGINTBlocked() {
|
||||
return sigismember(&mask, SIGINT);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func init() {
|
||||
register("CgoExecSignalMask", CgoExecSignalMask)
|
||||
}
|
||||
|
||||
func CgoExecSignalMask() {
|
||||
if len(os.Args) > 2 && os.Args[2] == "testsigint" {
|
||||
if C.SIGINTBlocked() != 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGTERM)
|
||||
go func() {
|
||||
for range c {
|
||||
}
|
||||
}()
|
||||
|
||||
const goCount = 10
|
||||
const execCount = 10
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(goCount*execCount + goCount)
|
||||
for i := 0; i < goCount; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for j := 0; j < execCount; j++ {
|
||||
c2 := make(chan os.Signal, 1)
|
||||
signal.Notify(c2, syscall.SIGUSR1)
|
||||
syscall.Kill(os.Getpid(), syscall.SIGTERM)
|
||||
go func(j int) {
|
||||
defer wg.Done()
|
||||
cmd := exec.Command(os.Args[0], "CgoExecSignalMask", "testsigint")
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
fmt.Printf("iteration %d: %v\n", j, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}(j)
|
||||
signal.Stop(c2)
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
fmt.Println("OK")
|
||||
}
|
Loading…
Reference in New Issue
Block a user