aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/proc.go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2017-06-12 22:36:03 -0700
committerIan Lance Taylor <iant@golang.org>2017-06-14 14:00:56 +0000
commitdf0892cbf854e76fae6e875043b05c194e37f52d (patch)
tree6d2ff62cf209f0f5bcaad476715d14a3caf8d667 /src/runtime/proc.go
parent17ba830f4663816c3270860fad96373a833a3b26 (diff)
downloadgo-df0892cbf854e76fae6e875043b05c194e37f52d.tar.xz
runtime, syscall: reset signal handlers to default in child
Block all signals during a fork. In the parent process, after the fork, restore the signal mask. In the child process, reset all currently handled signals to the default handler, and then restore the signal mask. The effect of this is that the child will be operating using the same signal regime as the program it is about to exec, as exec resets all non-ignored signals to the default, and preserves the signal mask. We do this so that in the case of a signal sent to the process group, the child process will not try to run a signal handler while in the precarious state after a fork. Fixes #18600. Change-Id: I9f39aaa3884035908d687ee323c975f349d5faaa Reviewed-on: https://go-review.googlesource.com/45471 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/proc.go')
-rw-r--r--src/runtime/proc.go32
1 files changed, 22 insertions, 10 deletions
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 9e53716992..f6e07f8ec0 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -2804,12 +2804,12 @@ func exitsyscall0(gp *g) {
func beforefork() {
gp := getg().m.curg
- // Fork can hang if preempted with signals frequently enough (see issue 5517).
- // Ensure that we stay on the same M where we disable profiling.
+ // Block signals during a fork, so that the child does not run
+ // a signal handler before exec if a signal is sent to the process
+ // group. See issue #18600.
gp.m.locks++
- if gp.m.profilehz != 0 {
- setThreadCPUProfiler(0)
- }
+ msigsave(gp.m)
+ sigblock()
// This function is called before fork in syscall package.
// Code between fork and exec must not allocate memory nor even try to grow stack.
@@ -2828,13 +2828,11 @@ func syscall_runtime_BeforeFork() {
func afterfork() {
gp := getg().m.curg
- // See the comment in beforefork.
+ // See the comments in beforefork.
gp.stackguard0 = gp.stack.lo + _StackGuard
- hz := sched.profilehz
- if hz != 0 {
- setThreadCPUProfiler(hz)
- }
+ msigrestore(gp.m.sigmask)
+
gp.m.locks--
}
@@ -2845,6 +2843,20 @@ func syscall_runtime_AfterFork() {
systemstack(afterfork)
}
+// Called from syscall package after fork in child.
+// It resets non-sigignored signals to the default handler, and
+// restores the signal mask in preparation for the exec.
+//go:linkname syscall_runtime_AfterForkInChild syscall.runtime_AfterForkInChild
+//go:nosplit
+//go:nowritebarrierrec
+func syscall_runtime_AfterForkInChild() {
+ clearSignalHandlers()
+
+ // When we are the child we are the only thread running,
+ // so we know that nothing else has changed gp.m.sigmask.
+ msigrestore(getg().m.sigmask)
+}
+
// Allocate a new g, with a stack big enough for stacksize bytes.
func malg(stacksize int32) *g {
newg := new(g)