From 72eef9d09307f0b437153fd152229f56edc0ab20 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Thu, 1 Dec 2016 12:58:41 +0100 Subject: [PATCH] bind: avoid crashes from SIGPIPE The Go runtime doesn't handle SIGIPE signals from writing to closed sockets or pipes in c-archive and c-shared mode (issue 17393). Work around it in gomobile by simply ignoring all SIGPIPE signals; they're not useful in mobile apps anyway. Change-Id: Ibd7ee41058856c5eddb4a519345a3851a29e9b44 Reviewed-on: https://go-review.googlesource.com/33771 Reviewed-by: David Crawshaw --- bind/java/SeqTest.java | 4 ++++ bind/objc/SeqTest.m | 4 ++++ bind/seq.go.support | 5 +++++ bind/testpkg/testpkg.go | 27 +++++++++++++++++++++++++++ 4 files changed, 40 insertions(+) diff --git a/bind/java/SeqTest.java b/bind/java/SeqTest.java index 1089fda..156e591 100644 --- a/bind/java/SeqTest.java +++ b/bind/java/SeqTest.java @@ -577,4 +577,8 @@ public class SeqTest extends InstrumentationTestCase { InitCaller initer = Testpkg.newInitCaller(); initer.init(); } + + public void testSIGPIPE() { + Testpkg.testSIGPIPE(); + } } diff --git a/bind/objc/SeqTest.m b/bind/objc/SeqTest.m index 8fd15cf..9962c68 100644 --- a/bind/objc/SeqTest.m +++ b/bind/objc/SeqTest.m @@ -449,4 +449,8 @@ static int numI = 0; XCTAssertFalse(GoTestpkgCallEmptyError(empty, &error), @"GoTestpkgCallEmptyError succeeded; want error"); XCTAssertNotNil(error, @"GoTestpkgCallEmptyError returned nil error"); } + +- (void)testSIGPIPE { + GoTestpkgTestSIGPIPE(); +} @end diff --git a/bind/seq.go.support b/bind/seq.go.support index d2f36d4..1167b6c 100644 --- a/bind/seq.go.support +++ b/bind/seq.go.support @@ -14,6 +14,9 @@ import "C" import ( "fmt" + "os" + "os/signal" + "syscall" _seq "golang.org/x/mobile/bind/seq" ) @@ -32,6 +35,8 @@ func init() { } C.go_seq_inc_ref(C.int32_t(refnum)) } + // Workaround for issue #17393. + signal.Notify(make(chan os.Signal), syscall.SIGPIPE) } // IncGoRef is called by foreign code to pin a Go object while its refnum is crossing diff --git a/bind/testpkg/testpkg.go b/bind/testpkg/testpkg.go index 5411f45..2e825c7 100644 --- a/bind/testpkg/testpkg.go +++ b/bind/testpkg/testpkg.go @@ -16,7 +16,9 @@ import ( "io/ioutil" "log" "math" + "os" "runtime" + "syscall" "time" "golang.org/x/mobile/asset" @@ -569,3 +571,28 @@ func NewS4WithBoolAndError(b bool) (*S4, error) { } return new(S4), nil } + +// Lifted from TestEPIPE in package os. +func TestSIGPIPE() { + r, w, err := os.Pipe() + if err != nil { + panic(err) + } + if err := r.Close(); err != nil { + panic(err) + } + + _, err = w.Write([]byte("hi")) + if err == nil { + panic("unexpected success of Write to broken pipe") + } + if pe, ok := err.(*os.PathError); ok { + err = pe.Err + } + if se, ok := err.(*os.SyscallError); ok { + err = se.Err + } + if err != syscall.EPIPE { + panic(fmt.Errorf("got %v, expected EPIPE", err)) + } +}