]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: don't try to free OS-created signal stacks
authorAustin Clements <austin@google.com>
Wed, 11 Oct 2017 21:04:26 +0000 (17:04 -0400)
committerAustin Clements <austin@google.com>
Wed, 11 Oct 2017 22:17:30 +0000 (22:17 +0000)
Android's libc creates a signal stack for every thread it creates. In
Go, minitSignalStack picks up this existing signal stack and puts it
in m.gsignal.stack. However, if we later try to exit a thread (because
a locked goroutine is exiting), we'll attempt to stackfree this
libc-allocated signal stack and panic.

Fix this by clearing gsignal.stack when we unminitSignals in such a
situation.

This should fix the Android build, which is currently broken.

Change-Id: Ieea8d72ef063d22741c54c9daddd8bb84926a488
Reviewed-on: https://go-review.googlesource.com/70130
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/runtime/proc.go
src/runtime/signal_unix.go

index 165b04eb433498402472ab58e78b3c0dff886340..d096df547ec88ac3e05c6bbc7a46f180165ea255 100644 (file)
@@ -1268,7 +1268,13 @@ func mexit(osStack bool) {
        unminit()
 
        // Free the gsignal stack.
-       if m.gsignal != nil {
+       //
+       // If the signal stack was created outside Go, then gsignal
+       // will be non-nil, but unminitSignals set stack.lo to 0
+       // (e.g., Android's libc creates all threads with a signal
+       // stack, so it's possible for Go to exit them but not control
+       // the signal stack).
+       if m.gsignal != nil && m.gsignal.stack.lo != 0 {
                stackfree(m.gsignal.stack)
        }
 
index 5ea4b9f63157d450d385178f2a0015e88162be08..a616d46bacf74c699065ca386c1954aa32546b4e 100644 (file)
@@ -744,6 +744,10 @@ func unminitSignals() {
        if getg().m.newSigstack {
                st := stackt{ss_flags: _SS_DISABLE}
                sigaltstack(&st, nil)
+       } else {
+               // We got the signal stack from someone else. Clear it
+               // so we don't get confused.
+               getg().m.gsignal.stack = stack{}
        }
 }