Commit 2afe9d4d authored by Elias Naur's avatar Elias Naur

runtime: don't forward SIGPIPE on macOS

macOS and iOS deliver SIGPIPE signals to the main thread and not
the thread that raised it by writing to a closed socket or pipe.

SIGPIPE signals can be suppressed for sockets with the SO_NOSIGPIPE
option, but there is no similar option for pipes. We have no other
choice but to never forward SIGPIPE on macOS.

This is a fixup of reverted CL 188297.

Fixes #33384

Change-Id: I09b258b078857ad3b22025bc2902d1b12d2afd92
Reviewed-on: https://go-review.googlesource.com/c/go/+/191785
Run-TryBot: Elias Naur <mail@eliasnaur.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 9f85668a
...@@ -282,7 +282,13 @@ func TestEarlySignalHandler(t *testing.T) { ...@@ -282,7 +282,13 @@ func TestEarlySignalHandler(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil { darwin := "0"
if runtime.GOOS == "darwin" {
darwin = "1"
}
cmd = exec.Command(bin[0], append(bin[1:], darwin)...)
if out, err := cmd.CombinedOutput(); err != nil {
t.Logf("%s", out) t.Logf("%s", out)
t.Fatal(err) t.Fatal(err)
} }
...@@ -320,12 +326,15 @@ func TestSignalForwarding(t *testing.T) { ...@@ -320,12 +326,15 @@ func TestSignalForwarding(t *testing.T) {
t.Logf("%s", out) t.Logf("%s", out)
expectSignal(t, err, syscall.SIGSEGV) expectSignal(t, err, syscall.SIGSEGV)
// SIGPIPE is never forwarded on darwin. See golang.org/issue/33384.
if runtime.GOOS != "darwin" {
// Test SIGPIPE forwarding // Test SIGPIPE forwarding
cmd = exec.Command(bin[0], append(bin[1:], "3")...) cmd = exec.Command(bin[0], append(bin[1:], "3")...)
out, err = cmd.CombinedOutput() out, err = cmd.CombinedOutput()
t.Logf("%s", out) t.Logf("%s", out)
expectSignal(t, err, syscall.SIGPIPE) expectSignal(t, err, syscall.SIGPIPE)
}
} }
func TestSignalForwardingExternal(t *testing.T) { func TestSignalForwardingExternal(t *testing.T) {
...@@ -744,11 +753,20 @@ func TestCompileWithoutShared(t *testing.T) { ...@@ -744,11 +753,20 @@ func TestCompileWithoutShared(t *testing.T) {
} }
defer os.Remove(exe) defer os.Remove(exe)
binArgs := append(cmdToRun(exe), "1")
t.Log(binArgs)
out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput()
t.Logf("%s", out)
expectSignal(t, err, syscall.SIGSEGV)
// SIGPIPE is never forwarded on darwin. See golang.org/issue/33384.
if runtime.GOOS != "darwin" {
binArgs := append(cmdToRun(exe), "3") binArgs := append(cmdToRun(exe), "3")
t.Log(binArgs) t.Log(binArgs)
out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput() out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput()
t.Logf("%s", out) t.Logf("%s", out)
expectSignal(t, err, syscall.SIGPIPE) expectSignal(t, err, syscall.SIGPIPE)
}
} }
// Test that installing a second time recreates the header files. // Test that installing a second time recreates the header files.
......
...@@ -123,8 +123,12 @@ int main(int argc, char** argv) { ...@@ -123,8 +123,12 @@ int main(int argc, char** argv) {
sigset_t mask; sigset_t mask;
int i; int i;
struct timespec ts; struct timespec ts;
int darwin;
darwin = atoi(argv[1]);
verbose = argc > 2;
verbose = argc > 1;
setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0);
// Call setsid so that we can use kill(0, SIGIO) below. // Call setsid so that we can use kill(0, SIGIO) below.
...@@ -186,6 +190,8 @@ int main(int argc, char** argv) { ...@@ -186,6 +190,8 @@ int main(int argc, char** argv) {
printf("provoking SIGPIPE\n"); printf("provoking SIGPIPE\n");
} }
// SIGPIPE is never forwarded on Darwin, see golang.org/issue/33384.
if (!darwin) {
GoRaiseSIGPIPE(); GoRaiseSIGPIPE();
if (verbose) { if (verbose) {
...@@ -204,6 +210,7 @@ int main(int argc, char** argv) { ...@@ -204,6 +210,7 @@ int main(int argc, char** argv) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
}
if (verbose) { if (verbose) {
printf("calling setjmp\n"); printf("calling setjmp\n");
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <time.h> #include <time.h>
#include <sched.h> #include <sched.h>
#include <unistd.h> #include <unistd.h>
#include <pthread.h>
#include "libgo3.h" #include "libgo3.h"
...@@ -51,11 +52,18 @@ static void init() { ...@@ -51,11 +52,18 @@ static void init() {
} }
} }
static void *provokeSIGPIPE(void *arg) {
ProvokeSIGPIPE();
return NULL;
}
int main(int argc, char** argv) { int main(int argc, char** argv) {
int verbose; int verbose;
struct sigaction sa; struct sigaction sa;
int i; int i;
struct timespec ts; struct timespec ts;
int res;
pthread_t tid;
verbose = argc > 2; verbose = argc > 2;
setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0);
...@@ -68,6 +76,19 @@ int main(int argc, char** argv) { ...@@ -68,6 +76,19 @@ int main(int argc, char** argv) {
// a non-default SIGPIPE handler before the runtime initializes. // a non-default SIGPIPE handler before the runtime initializes.
ProvokeSIGPIPE(); ProvokeSIGPIPE();
// Test that SIGPIPE on a non-main thread is also handled by Go.
res = pthread_create(&tid, NULL, provokeSIGPIPE, NULL);
if (res != 0) {
fprintf(stderr, "pthread_create: %s\n", strerror(res));
exit(EXIT_FAILURE);
}
res = pthread_join(tid, NULL);
if (res != 0) {
fprintf(stderr, "pthread_join: %s\n", strerror(res));
exit(EXIT_FAILURE);
}
if (verbose) { if (verbose) {
printf("calling sigaction\n"); printf("calling sigaction\n");
} }
......
...@@ -636,6 +636,13 @@ func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool { ...@@ -636,6 +636,13 @@ func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool {
return true return true
} }
// This function and its caller sigtrampgo assumes SIGPIPE is delivered on the
// originating thread. This property does not hold on macOS (golang.org/issue/33384),
// so we have no choice but to ignore SIGPIPE.
if GOOS == "darwin" && sig == _SIGPIPE {
return true
}
// If there is no handler to forward to, no need to forward. // If there is no handler to forward to, no need to forward.
if fwdFn == _SIG_DFL { if fwdFn == _SIG_DFL {
return false return false
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment