aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippo Valsorda <filippo@golang.org>2020-12-07 12:33:50 +0100
committerFilippo Valsorda <filippo@golang.org>2020-12-07 12:33:50 +0100
commit2bb8e5a94e8ad214ab78dc4b953c98e9f3881d09 (patch)
tree320f823cc3eaed22371cff476c8ad12d3e0d97a4
parent21ba30ad409aeef21739af9b574e04d0d66945a0 (diff)
parent6eed7d361d276b69a1cfdeeb7690237a6385b073 (diff)
downloadgo-2bb8e5a94e8ad214ab78dc4b953c98e9f3881d09.tar.gz
go-2bb8e5a94e8ad214ab78dc4b953c98e9f3881d09.zip
[dev.boringcrypto.go1.14] all: merge go1.14.13 into dev.boringcrypto.go1.14
Change-Id: I129644772ec86e5a18b3171115c82811612f0e7f
-rw-r--r--src/cmd/compile/internal/ssa/gen/AMD64.rules6
-rw-r--r--src/cmd/compile/internal/ssa/rewriteAMD64.go12
-rw-r--r--src/cmd/go/internal/work/exec.go15
-rw-r--r--src/cmd/go/testdata/script/ldflag.txt44
-rw-r--r--src/runtime/crash_cgo_test.go13
-rw-r--r--src/runtime/os_js.go2
-rw-r--r--src/runtime/os_plan9.go2
-rw-r--r--src/runtime/os_windows.go2
-rw-r--r--src/runtime/proc.go26
-rw-r--r--src/runtime/signal_unix.go8
-rw-r--r--src/runtime/testdata/testprogcgo/needmdeadlock.go95
-rw-r--r--test/fixedbugs/issue42753.go13
12 files changed, 212 insertions, 26 deletions
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules
index 2d662d5ae6..f819aefcfd 100644
--- a/src/cmd/compile/internal/ssa/gen/AMD64.rules
+++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules
@@ -1465,11 +1465,11 @@
(NOTQ (MOVQconst [c])) -> (MOVQconst [^c])
(NOTL (MOVLconst [c])) -> (MOVLconst [^c])
(BTSQconst [c] (MOVQconst [d])) -> (MOVQconst [d|(1<<uint32(c))])
-(BTSLconst [c] (MOVLconst [d])) -> (MOVLconst [d|(1<<uint32(c))])
+(BTSLconst [c] (MOVLconst [d])) -> (MOVLconst [int64(int32(d|(1<<uint32(c))))])
(BTRQconst [c] (MOVQconst [d])) -> (MOVQconst [d&^(1<<uint32(c))])
-(BTRLconst [c] (MOVLconst [d])) -> (MOVLconst [d&^(1<<uint32(c))])
+(BTRLconst [c] (MOVLconst [d])) -> (MOVLconst [int64(int32(d&^(1<<uint32(c))))])
(BTCQconst [c] (MOVQconst [d])) -> (MOVQconst [d^(1<<uint32(c))])
-(BTCLconst [c] (MOVLconst [d])) -> (MOVLconst [d^(1<<uint32(c))])
+(BTCLconst [c] (MOVLconst [d])) -> (MOVLconst [int64(int32(d^(1<<uint32(c))))])
// generic simplifications
// TODO: more of this
diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go
index c104157cec..366eac0706 100644
--- a/src/cmd/compile/internal/ssa/rewriteAMD64.go
+++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go
@@ -4326,7 +4326,7 @@ func rewriteValueAMD64_OpAMD64BTCLconst_0(v *Value) bool {
return true
}
// match: (BTCLconst [c] (MOVLconst [d]))
- // result: (MOVLconst [d^(1<<uint32(c))])
+ // result: (MOVLconst [int64(int32(d^(1<<uint32(c))))])
for {
c := v.AuxInt
v_0 := v.Args[0]
@@ -4335,7 +4335,7 @@ func rewriteValueAMD64_OpAMD64BTCLconst_0(v *Value) bool {
}
d := v_0.AuxInt
v.reset(OpAMD64MOVLconst)
- v.AuxInt = d ^ (1 << uint32(c))
+ v.AuxInt = int64(int32(d ^ (1 << uint32(c))))
return true
}
return false
@@ -4825,7 +4825,7 @@ func rewriteValueAMD64_OpAMD64BTRLconst_0(v *Value) bool {
return true
}
// match: (BTRLconst [c] (MOVLconst [d]))
- // result: (MOVLconst [d&^(1<<uint32(c))])
+ // result: (MOVLconst [int64(int32(d&^(1<<uint32(c))))])
for {
c := v.AuxInt
v_0 := v.Args[0]
@@ -4834,7 +4834,7 @@ func rewriteValueAMD64_OpAMD64BTRLconst_0(v *Value) bool {
}
d := v_0.AuxInt
v.reset(OpAMD64MOVLconst)
- v.AuxInt = d &^ (1 << uint32(c))
+ v.AuxInt = int64(int32(d &^ (1 << uint32(c))))
return true
}
return false
@@ -5181,7 +5181,7 @@ func rewriteValueAMD64_OpAMD64BTSLconst_0(v *Value) bool {
return true
}
// match: (BTSLconst [c] (MOVLconst [d]))
- // result: (MOVLconst [d|(1<<uint32(c))])
+ // result: (MOVLconst [int64(int32(d|(1<<uint32(c))))])
for {
c := v.AuxInt
v_0 := v.Args[0]
@@ -5190,7 +5190,7 @@ func rewriteValueAMD64_OpAMD64BTSLconst_0(v *Value) bool {
}
d := v_0.AuxInt
v.reset(OpAMD64MOVLconst)
- v.AuxInt = d | (1 << uint32(c))
+ v.AuxInt = int64(int32(d | (1 << uint32(c))))
return true
}
return false
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index 6e20c055fa..a87bc802c1 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -2687,6 +2687,21 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
idx = bytes.Index(src, []byte(cgoLdflag))
}
}
+
+ // We expect to find the contents of cgoLDFLAGS in flags.
+ if len(cgoLDFLAGS) > 0 {
+ outer:
+ for i := range flags {
+ for j, f := range cgoLDFLAGS {
+ if f != flags[i+j] {
+ continue outer
+ }
+ }
+ flags = append(flags[:i], flags[i+len(cgoLDFLAGS):]...)
+ break
+ }
+ }
+
if err := checkLinkerFlags("LDFLAGS", "go:cgo_ldflag", flags); err != nil {
return nil, nil, err
}
diff --git a/src/cmd/go/testdata/script/ldflag.txt b/src/cmd/go/testdata/script/ldflag.txt
new file mode 100644
index 0000000000..6ceb33bb70
--- /dev/null
+++ b/src/cmd/go/testdata/script/ldflag.txt
@@ -0,0 +1,44 @@
+# Issue #42565
+
+[!cgo] skip
+
+# We can't build package bad, which uses #cgo LDFLAGS.
+cd bad
+! go build
+stderr no-such-warning
+
+# We can build package ok with the same flags in CGO_LDFLAGS.
+env CGO_LDFLAGS=-Wno-such-warning -Wno-unknown-warning-option
+cd ../ok
+go build
+
+# Build a main program that actually uses LDFLAGS.
+cd ..
+go build -ldflags=-v
+
+# Because we passed -v the Go linker should print the external linker
+# command which should include the flag we passed in CGO_LDFLAGS.
+stderr no-such-warning
+
+-- go.mod --
+module ldflag
+
+-- bad/bad.go --
+package bad
+
+// #cgo LDFLAGS: -Wno-such-warning -Wno-unknown-warning
+import "C"
+
+func F() {}
+-- ok/ok.go --
+package ok
+
+import "C"
+
+func F() {}
+-- main.go --
+package main
+
+import _ "ldflag/ok"
+
+func main() {}
diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
index 56cfb0856e..6e032df8b1 100644
--- a/src/runtime/crash_cgo_test.go
+++ b/src/runtime/crash_cgo_test.go
@@ -549,3 +549,16 @@ func findTrace(text, top string) []string {
}
return nil
}
+
+// Issue #42207.
+func TestNeedmDeadlock(t *testing.T) {
+ switch runtime.GOOS {
+ case "plan9", "windows":
+ t.Skipf("no signals on %s", runtime.GOOS)
+ }
+ output := runTestProg(t, "testprogcgo", "NeedmDeadlock")
+ want := "OK\n"
+ if output != want {
+ t.Fatalf("want %s, got %s\n", want, output)
+ }
+}
diff --git a/src/runtime/os_js.go b/src/runtime/os_js.go
index ff0ee3aa6b..94983b358d 100644
--- a/src/runtime/os_js.go
+++ b/src/runtime/os_js.go
@@ -59,7 +59,7 @@ func mpreinit(mp *m) {
}
//go:nosplit
-func msigsave(mp *m) {
+func sigsave(p *sigset) {
}
//go:nosplit
diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go
index b534cdba5d..8f9f0ca028 100644
--- a/src/runtime/os_plan9.go
+++ b/src/runtime/os_plan9.go
@@ -167,7 +167,7 @@ func mpreinit(mp *m) {
mp.errstr = (*byte)(mallocgc(_ERRMAX, nil, true))
}
-func msigsave(mp *m) {
+func sigsave(p *sigset) {
}
func msigrestore(sigmask sigset) {
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
index 4aaa31848a..ddfa2ca936 100644
--- a/src/runtime/os_windows.go
+++ b/src/runtime/os_windows.go
@@ -832,7 +832,7 @@ func mpreinit(mp *m) {
}
//go:nosplit
-func msigsave(mp *m) {
+func sigsave(p *sigset) {
}
//go:nosplit
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 76a71be123..8509bd304e 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -551,7 +551,7 @@ func schedinit() {
typelinksinit() // uses maps, activeModules
itabsinit() // uses activeModules
- msigsave(_g_.m)
+ sigsave(&_g_.m.sigmask)
initSigmask = _g_.m.sigmask
goargs()
@@ -1476,6 +1476,18 @@ func needm(x byte) {
exit(1)
}
+ // Save and block signals before getting an M.
+ // The signal handler may call needm itself,
+ // and we must avoid a deadlock. Also, once g is installed,
+ // any incoming signals will try to execute,
+ // but we won't have the sigaltstack settings and other data
+ // set up appropriately until the end of minit, which will
+ // unblock the signals. This is the same dance as when
+ // starting a new m to run Go code via newosproc.
+ var sigmask sigset
+ sigsave(&sigmask)
+ sigblock()
+
// Lock extra list, take head, unlock popped list.
// nilokay=false is safe here because of the invariant above,
// that the extra list always contains or will soon contain
@@ -1493,14 +1505,8 @@ func needm(x byte) {
extraMCount--
unlockextra(mp.schedlink.ptr())
- // Save and block signals before installing g.
- // Once g is installed, any incoming signals will try to execute,
- // but we won't have the sigaltstack settings and other data
- // set up appropriately until the end of minit, which will
- // unblock the signals. This is the same dance as when
- // starting a new m to run Go code via newosproc.
- msigsave(mp)
- sigblock()
+ // Store the original signal mask for use by minit.
+ mp.sigmask = sigmask
// Install g (= m->g0) and set the stack bounds
// to match the current stack. We don't actually know
@@ -3317,7 +3323,7 @@ func beforefork() {
// a signal handler before exec if a signal is sent to the process
// group. See issue #18600.
gp.m.locks++
- msigsave(gp.m)
+ sigsave(&gp.m.sigmask)
sigblock()
// This function is called before fork in syscall package.
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go
index 9f081d41c5..fa0b5bb516 100644
--- a/src/runtime/signal_unix.go
+++ b/src/runtime/signal_unix.go
@@ -1007,15 +1007,15 @@ func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool {
return true
}
-// msigsave saves the current thread's signal mask into mp.sigmask.
+// sigsave saves the current thread's signal mask into *p.
// This is used to preserve the non-Go signal mask when a non-Go
// thread calls a Go function.
// This is nosplit and nowritebarrierrec because it is called by needm
// which may be called on a non-Go thread with no g available.
//go:nosplit
//go:nowritebarrierrec
-func msigsave(mp *m) {
- sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
+func sigsave(p *sigset) {
+ sigprocmask(_SIG_SETMASK, nil, p)
}
// msigrestore sets the current thread's signal mask to sigmask.
@@ -1087,7 +1087,7 @@ func minitSignalStack() {
// thread's signal mask. When this is called all signals have been
// blocked for the thread. This starts with m.sigmask, which was set
// either from initSigmask for a newly created thread or by calling
-// msigsave if this is a non-Go thread calling a Go function. It
+// sigsave if this is a non-Go thread calling a Go function. It
// removes all essential signals from the mask, thus causing those
// signals to not be blocked. Then it sets the thread's signal mask.
// After this is called the thread can receive signals.
diff --git a/src/runtime/testdata/testprogcgo/needmdeadlock.go b/src/runtime/testdata/testprogcgo/needmdeadlock.go
new file mode 100644
index 0000000000..5a9c359006
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/needmdeadlock.go
@@ -0,0 +1,95 @@
+// Copyright 2020 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
+
+// This is for issue #42207.
+// During a call to needm we could get a SIGCHLD signal
+// which would itself call needm, causing a deadlock.
+
+/*
+#include <signal.h>
+#include <pthread.h>
+#include <sched.h>
+#include <unistd.h>
+
+extern void GoNeedM();
+
+#define SIGNALERS 10
+
+static void* needmSignalThread(void* p) {
+ pthread_t* pt = (pthread_t*)(p);
+ int i;
+
+ for (i = 0; i < 100; i++) {
+ if (pthread_kill(*pt, SIGCHLD) < 0) {
+ return NULL;
+ }
+ usleep(1);
+ }
+ return NULL;
+}
+
+// We don't need many calls, as the deadlock is only likely
+// to occur the first couple of times that needm is called.
+// After that there will likely be an extra M available.
+#define CALLS 10
+
+static void* needmCallbackThread(void* p) {
+ int i;
+
+ for (i = 0; i < SIGNALERS; i++) {
+ sched_yield(); // Help the signal threads get started.
+ }
+ for (i = 0; i < CALLS; i++) {
+ GoNeedM();
+ }
+ return NULL;
+}
+
+static void runNeedmSignalThread() {
+ int i;
+ pthread_t caller;
+ pthread_t s[SIGNALERS];
+
+ pthread_create(&caller, NULL, needmCallbackThread, NULL);
+ for (i = 0; i < SIGNALERS; i++) {
+ pthread_create(&s[i], NULL, needmSignalThread, &caller);
+ }
+ for (i = 0; i < SIGNALERS; i++) {
+ pthread_join(s[i], NULL);
+ }
+ pthread_join(caller, NULL);
+}
+*/
+import "C"
+
+import (
+ "fmt"
+ "os"
+ "time"
+)
+
+func init() {
+ register("NeedmDeadlock", NeedmDeadlock)
+}
+
+//export GoNeedM
+func GoNeedM() {
+}
+
+func NeedmDeadlock() {
+ // The failure symptom is that the program hangs because of a
+ // deadlock in needm, so set an alarm.
+ go func() {
+ time.Sleep(5 * time.Second)
+ fmt.Println("Hung for 5 seconds")
+ os.Exit(1)
+ }()
+
+ C.runNeedmSignalThread()
+ fmt.Println("OK")
+}
diff --git a/test/fixedbugs/issue42753.go b/test/fixedbugs/issue42753.go
new file mode 100644
index 0000000000..a998d1d3b3
--- /dev/null
+++ b/test/fixedbugs/issue42753.go
@@ -0,0 +1,13 @@
+// compile -d=ssa/check/on
+
+// Copyright 2020 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.
+
+package main
+
+func f() uint32 {
+ s := "\x01"
+ x := -int32(s[0])
+ return uint32(x) & 0x7fffffff
+}