Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: SIGPIPE from non-main threads not caught by Go on macOS/iOS #33384

Closed
eliasnaur opened this issue Jul 31, 2019 · 9 comments
Closed

runtime: SIGPIPE from non-main threads not caught by Go on macOS/iOS #33384

eliasnaur opened this issue Jul 31, 2019 · 9 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Darwin
Milestone

Comments

@eliasnaur
Copy link
Contributor

eliasnaur commented Jul 31, 2019

What version of Go are you using (go version)?

$ go version
go version devel +d40f3a19b9 Wed Jul 31 14:37:10 2019 +0200 darwin/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/elias/Library/Caches/go-build"
GOENV="/Users/elias/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/elias/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/Users/elias/go-tip"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/Users/elias/go-tip/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/elias/go-tip/misc/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/_7/lnt35k555hl2bs7fjygkhgx00000gp/T/go-build504643451=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

Patched in https://golang.org/cl/188297 and ran

$ cd misc/cgo/testcarchive
$ go test -v -run OsSig -count=1 .
=== RUN   TestOsSignal
--- FAIL: TestOsSignal (1.65s)
    carchive_test.go:478: unexpected SIGPIPE
    carchive_test.go:479: exit status 1
FAIL
FAIL	misc/cgo/testcarchive	1.856s
FAIL

What did you expect to see?

No error.

What did you see instead?

Unexpected SIGPIPE from ProvokeSIGPIPE called on a non-main thread.

ProvokeSIGPIPE raises a SIGPIPE from a write to a closed pipe. It is a Go function so the Go runtime should catch it. Alas, it doesn't and the reason appears to be that the signal is raised on the main thread regardless of the raising thread.

To prove my claim, here is a backtrace from running the modified libgo3 test in lldb:

$ lldb ./testp
(lldb) target create "./testp"
Current executable set to './testp' (x86_64).
(lldb) b main
Breakpoint 1: 14 locations.
(lldb) run
Process 14147 launched: '/Users/elias/go-tip/misc/cgo/testcarchive/testp' (x86_64)
4 locations added to breakpoint 1
Process 14147 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100001580 testp`main
testp`main:
->  0x100001580 <+0>:  pushq  %rbp
    0x100001581 <+1>:  movq   %rsp, %rbp
    0x100001584 <+4>:  subq   $0xd0, %rsp
    0x10000158b <+11>: xorl   %eax, %eax
Target 0: (testp) stopped.
(lldb) process handle SIGPIPE -s true                                                                                                                                         NAME         PASS   STOP   NOTIFY
===========  =====  =====  ======
SIGPIPE      true   true   false
(lldb) cont
Process 14147 resuming
Process 14147 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGPIPE
    frame #0: 0x00007fff6af789de libsystem_kernel.dylib`__ulock_wait + 10
libsystem_kernel.dylib`__ulock_wait:
->  0x7fff6af789de <+10>: jae    0x7fff6af789e8            ; <+20>
    0x7fff6af789e0 <+12>: movq   %rax, %rdi
    0x7fff6af789e3 <+15>: jmp    0x7fff6af76457            ; cerror_nocancel
    0x7fff6af789e8 <+20>: retq
Target 0: (testp) stopped.
(lldb) bt all
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGPIPE
  * frame #0: 0x00007fff6af789de libsystem_kernel.dylib`__ulock_wait + 10
    frame #1: 0x00007fff6b0396de libsystem_pthread.dylib`_pthread_join + 358
    frame #2: 0x0000000100001658 testp`main + 216
    frame #3: 0x00007fff6ae413d5 libdyld.dylib`start + 1
  thread #2
    frame #0: 0x00007fff6af7986a libsystem_kernel.dylib`__psynch_cvwait + 10
    frame #1: 0x00007fff6b03856e libsystem_pthread.dylib`_pthread_cond_wait + 722
    frame #2: 0x0000000100055fe0 testp`runtime.pthread_cond_wait_trampoline + 16
    frame #3: 0x000000010005399d testp`runtime.asmcgocall + 173
    frame #4: 0x0000000100055fd0 testp`runtime.pthread_cond_init_trampoline + 32
    frame #5: 0x0000000100045a09 testp`runtime.pthread_cond_wait + 57
    frame #6: 0x0000000100027a45 testp`runtime.semasleep + 133
    frame #7: 0x000000010000a2f0 testp`runtime.notesleep + 224
    frame #8: 0x000000010002fa30 testp`runtime.stopm + 192
    frame #9: 0x0000000100030342 testp`runtime.startlockedm + 130
    frame #10: 0x00000001000315a9 testp`runtime.schedule + 105
    frame #11: 0x0000000100032226 testp`runtime.goexit0 + 470
    frame #12: 0x00000001000520fb testp`runtime.mcall + 91
    frame #13: 0x0000000100027a45 testp`runtime.semasleep + 133
    frame #14: 0x000000010000a2f0 testp`runtime.notesleep + 224
    frame #15: 0x000000010002fa30 testp`runtime.stopm + 192
    frame #16: 0x0000000100030342 testp`runtime.startlockedm + 130
    frame #17: 0x00000001000315a9 testp`runtime.schedule + 105
    frame #18: 0x0000000100032226 testp`runtime.goexit0 + 470
    frame #19: 0x00000001000520fb testp`runtime.mcall + 91
    frame #20: 0x000000010000a2f0 testp`runtime.notesleep + 224
    frame #21: 0x000000010002fa30 testp`runtime.stopm + 192
    frame #22: 0x0000000100030342 testp`runtime.startlockedm + 130
    frame #23: 0x00000001000315a9 testp`runtime.schedule + 105
    frame #24: 0x0000000100032226 testp`runtime.goexit0 + 470
    frame #25: 0x00000001000520fb testp`runtime.mcall + 91
    frame #26: 0x000000010002fa30 testp`runtime.stopm + 192
    frame #27: 0x0000000100030342 testp`runtime.startlockedm + 130
    frame #28: 0x00000001000315a9 testp`runtime.schedule + 105
    frame #29: 0x0000000100032226 testp`runtime.goexit0 + 470
    frame #30: 0x00000001000520fb testp`runtime.mcall + 91
    frame #31: 0x0000000100030342 testp`runtime.startlockedm + 130
    frame #32: 0x00000001000315a9 testp`runtime.schedule + 105
    frame #33: 0x0000000100032226 testp`runtime.goexit0 + 470
    frame #34: 0x00000001000520fb testp`runtime.mcall + 91
    frame #35: 0x00000001000315a9 testp`runtime.schedule + 105
    frame #36: 0x0000000100032226 testp`runtime.goexit0 + 470
    frame #37: 0x00000001000520fb testp`runtime.mcall + 91
    frame #38: 0x0000000100032226 testp`runtime.goexit0 + 470
    frame #39: 0x00000001000520fb testp`runtime.mcall + 91
    frame #40: 0x00000001000520fb testp`runtime.mcall + 91
    frame #41: 0x00000001000541c6 testp`runtime.goexit + 6
  thread #3
    frame #0: 0x000000010003b06a testp`runtime.semrelease1 + 106
    frame #1: 0x000000010003ac99 testp`internal/poll.runtime_Semrelease + 57
    frame #2: 0x000000010006a1c1 testp`internal/poll.(*FD).destroy + 113
    frame #3: 0x0000000100069ae2 testp`internal/poll.(*FD).decref + 66
    frame #4: 0x000000010006a25f testp`internal/poll.(*FD).Close + 79
    frame #5: 0x000000010006c8ad testp`os.(*file).close + 77
    frame #6: 0x000000010006c813 testp`os.(*File).Close + 51
    frame #7: 0x000000010007025e testp`main.ProvokeSIGPIPE + 206
    frame #8: 0x0000000100070070 testp`main._cgoexpwrap_956550655198_ProvokeSIGPIPE + 32
    frame #9: 0x00000001000524cb testp`runtime.call32 + 59
    frame #10: 0x00000001000043b7 testp`runtime.cgocallbackg1 + 439
    frame #11: 0x0000000100004161 testp`runtime.cgocallbackg + 193
    frame #12: 0x0000000100053a9b testp`runtime.cgocallback_gofunc + 155
    frame #13: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #14: 0x000000010003ac99 testp`internal/poll.runtime_Semrelease + 57
    frame #15: 0x000000010006a1c1 testp`internal/poll.(*FD).destroy + 113
    frame #16: 0x0000000100069ae2 testp`internal/poll.(*FD).decref + 66
    frame #17: 0x000000010006a25f testp`internal/poll.(*FD).Close + 79
    frame #18: 0x000000010006c8ad testp`os.(*file).close + 77
    frame #19: 0x000000010006c813 testp`os.(*File).Close + 51
    frame #20: 0x000000010007025e testp`main.ProvokeSIGPIPE + 206
    frame #21: 0x0000000100070070 testp`main._cgoexpwrap_956550655198_ProvokeSIGPIPE + 32
    frame #22: 0x00000001000524cb testp`runtime.call32 + 59
    frame #23: 0x00000001000043b7 testp`runtime.cgocallbackg1 + 439
    frame #24: 0x0000000100004161 testp`runtime.cgocallbackg + 193
    frame #25: 0x0000000100053a9b testp`runtime.cgocallback_gofunc + 155
    frame #26: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #27: 0x000000010006a1c1 testp`internal/poll.(*FD).destroy + 113
    frame #28: 0x0000000100069ae2 testp`internal/poll.(*FD).decref + 66
    frame #29: 0x000000010006a25f testp`internal/poll.(*FD).Close + 79
    frame #30: 0x000000010006c8ad testp`os.(*file).close + 77
    frame #31: 0x000000010006c813 testp`os.(*File).Close + 51
    frame #32: 0x000000010007025e testp`main.ProvokeSIGPIPE + 206
    frame #33: 0x0000000100070070 testp`main._cgoexpwrap_956550655198_ProvokeSIGPIPE + 32
    frame #34: 0x00000001000524cb testp`runtime.call32 + 59
    frame #35: 0x00000001000043b7 testp`runtime.cgocallbackg1 + 439
    frame #36: 0x0000000100004161 testp`runtime.cgocallbackg + 193
    frame #37: 0x0000000100053a9b testp`runtime.cgocallback_gofunc + 155
    frame #38: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #39: 0x0000000100069ae2 testp`internal/poll.(*FD).decref + 66
    frame #40: 0x000000010006a25f testp`internal/poll.(*FD).Close + 79
    frame #41: 0x000000010006c8ad testp`os.(*file).close + 77
    frame #42: 0x000000010006c813 testp`os.(*File).Close + 51
    frame #43: 0x000000010007025e testp`main.ProvokeSIGPIPE + 206
    frame #44: 0x0000000100070070 testp`main._cgoexpwrap_956550655198_ProvokeSIGPIPE + 32
    frame #45: 0x00000001000524cb testp`runtime.call32 + 59
    frame #46: 0x00000001000043b7 testp`runtime.cgocallbackg1 + 439
    frame #47: 0x0000000100004161 testp`runtime.cgocallbackg + 193
    frame #48: 0x0000000100053a9b testp`runtime.cgocallback_gofunc + 155
    frame #49: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #50: 0x000000010006a25f testp`internal/poll.(*FD).Close + 79
    frame #51: 0x000000010006c8ad testp`os.(*file).close + 77
    frame #52: 0x000000010006c813 testp`os.(*File).Close + 51
    frame #53: 0x000000010007025e testp`main.ProvokeSIGPIPE + 206
    frame #54: 0x0000000100070070 testp`main._cgoexpwrap_956550655198_ProvokeSIGPIPE + 32
    frame #55: 0x00000001000524cb testp`runtime.call32 + 59
    frame #56: 0x00000001000043b7 testp`runtime.cgocallbackg1 + 439
    frame #57: 0x0000000100004161 testp`runtime.cgocallbackg + 193
    frame #58: 0x0000000100053a9b testp`runtime.cgocallback_gofunc + 155
    frame #59: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #60: 0x000000010006c8ad testp`os.(*file).close + 77
    frame #61: 0x000000010006c813 testp`os.(*File).Close + 51
    frame #62: 0x000000010007025e testp`main.ProvokeSIGPIPE + 206
    frame #63: 0x0000000100070070 testp`main._cgoexpwrap_956550655198_ProvokeSIGPIPE + 32
    frame #64: 0x00000001000524cb testp`runtime.call32 + 59
    frame #65: 0x00000001000043b7 testp`runtime.cgocallbackg1 + 439
    frame #66: 0x0000000100004161 testp`runtime.cgocallbackg + 193
    frame #67: 0x0000000100053a9b testp`runtime.cgocallback_gofunc + 155
    frame #68: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #69: 0x000000010006c813 testp`os.(*File).Close + 51
    frame #70: 0x000000010007025e testp`main.ProvokeSIGPIPE + 206
    frame #71: 0x0000000100070070 testp`main._cgoexpwrap_956550655198_ProvokeSIGPIPE + 32
    frame #72: 0x00000001000524cb testp`runtime.call32 + 59
    frame #73: 0x00000001000043b7 testp`runtime.cgocallbackg1 + 439
    frame #74: 0x0000000100004161 testp`runtime.cgocallbackg + 193
    frame #75: 0x0000000100053a9b testp`runtime.cgocallback_gofunc + 155
    frame #76: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #77: 0x000000010007025e testp`main.ProvokeSIGPIPE + 206
    frame #78: 0x0000000100070070 testp`main._cgoexpwrap_956550655198_ProvokeSIGPIPE + 32
    frame #79: 0x00000001000524cb testp`runtime.call32 + 59
    frame #80: 0x00000001000043b7 testp`runtime.cgocallbackg1 + 439
    frame #81: 0x0000000100004161 testp`runtime.cgocallbackg + 193
    frame #82: 0x0000000100053a9b testp`runtime.cgocallback_gofunc + 155
    frame #83: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #84: 0x0000000100070070 testp`main._cgoexpwrap_956550655198_ProvokeSIGPIPE + 32
    frame #85: 0x00000001000524cb testp`runtime.call32 + 59
    frame #86: 0x00000001000043b7 testp`runtime.cgocallbackg1 + 439
    frame #87: 0x0000000100004161 testp`runtime.cgocallbackg + 193
    frame #88: 0x0000000100053a9b testp`runtime.cgocallback_gofunc + 155
    frame #89: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #90: 0x00000001000524cb testp`runtime.call32 + 59
    frame #91: 0x00000001000043b7 testp`runtime.cgocallbackg1 + 439
    frame #92: 0x0000000100004161 testp`runtime.cgocallbackg + 193
    frame #93: 0x0000000100053a9b testp`runtime.cgocallback_gofunc + 155
    frame #94: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #95: 0x00000001000043b7 testp`runtime.cgocallbackg1 + 439
    frame #96: 0x0000000100004161 testp`runtime.cgocallbackg + 193
    frame #97: 0x0000000100053a9b testp`runtime.cgocallback_gofunc + 155
    frame #98: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #99: 0x0000000100004161 testp`runtime.cgocallbackg + 193
    frame #100: 0x0000000100053a9b testp`runtime.cgocallback_gofunc + 155
    frame #101: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #102: 0x0000000100053a9b testp`runtime.cgocallback_gofunc + 155
    frame #103: 0x00000001000539ee testp`runtime.cgocallback + 62
    frame #104: 0x0000000100070037 testp`_cgoexp_956550655198_ProvokeSIGPIPE + 71
    frame #105: 0x000000010005a937 testp`crosscall2 + 55
    frame #106: 0x00000001000703c3 testp`ProvokeSIGPIPE at _cgo_export.c:75:2 [opt]
    frame #107: 0x0000000100070037 testp`_cgoexp_956550655198_ProvokeSIGPIPE + 71
    frame #108: 0x000000010005a937 testp`crosscall2 + 55
    frame #109: 0x000000010005a937 testp`crosscall2 + 55
    frame #110: 0x00000001000703c3 testp`ProvokeSIGPIPE at _cgo_export.c:75:2 [opt]
    frame #111: 0x00000001000703c3 testp`ProvokeSIGPIPE at _cgo_export.c:75:2 [opt]
    frame #112: 0x0000000100001ac3 testp`provokeSIGPIPE + 19
    frame #113: 0x00007fff6b0352eb libsystem_pthread.dylib`_pthread_body + 126
    frame #114: 0x00007fff6b038249 libsystem_pthread.dylib`_pthread_start + 66
    frame #115: 0x00007fff6b03440d libsystem_pthread.dylib`thread_start + 13
  thread #4
    frame #0: 0x00007fff6af79f32 libsystem_kernel.dylib`__semwait_signal + 10
    frame #1: 0x00007fff6af05914 libsystem_c.dylib`nanosleep + 199
    frame #2: 0x00007fff6af05808 libsystem_c.dylib`usleep + 53
    frame #3: 0x0000000100055deb testp`runtime.usleep_trampoline + 11
    frame #4: 0x000000010005399d testp`runtime.asmcgocall + 173
    frame #5: 0x0000000100045431 testp`runtime.usleep + 49
    frame #6: 0x0000000100035b6d testp`runtime.sysmon + 141
    frame #7: 0x000000010002e6a3 testp`runtime.mstart1 + 195
    frame #8: 0x000000010002e5c6 testp`runtime.mstart + 102
    frame #9: 0x000000010007092d testp`crosscall_amd64 at gcc_amd64.S:35
    frame #10: 0x0000000100070584 testp`threadentry(v=<unavailable>) at gcc_darwin_amd64.c:64:2 [opt]
    frame #11: 0x00007fff6b0352eb libsystem_pthread.dylib`_pthread_body + 126
    frame #12: 0x00007fff6b038249 libsystem_pthread.dylib`_pthread_start + 66
    frame #13: 0x00007fff6b03440d libsystem_pthread.dylib`thread_start + 13
  thread #5
    frame #0: 0x00000001000306d5 testp`runtime.findrunnable + 197
    frame #1: 0x00000001000317fe testp`runtime.schedule + 702
    frame #2: 0x0000000100031b3d testp`runtime.park_m + 157
    frame #3: 0x00000001000520fb testp`runtime.mcall + 91
    frame #4: 0x00000001000317fe testp`runtime.schedule + 702
    frame #5: 0x0000000100031b3d testp`runtime.park_m + 157
    frame #6: 0x00000001000520fb testp`runtime.mcall + 91
    frame #7: 0x0000000100031b3d testp`runtime.park_m + 157
    frame #8: 0x00000001000520fb testp`runtime.mcall + 91
    frame #9: 0x00000001000520fb testp`runtime.mcall + 91
    frame #10: 0x000000010001ee81 testp`runtime.bgscavenge + 225
    frame #11: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #12: 0x00000001000541c1 testp`runtime.goexit + 1
  thread #6
    frame #0: 0x00007fff6af77ef2 libsystem_kernel.dylib`read + 10
    frame #1: 0x0000000100055a82 testp`runtime.read_trampoline + 18
    frame #2: 0x0000000100053960 testp`runtime.asmcgocall + 112
    frame #3: 0x000000010002e560 testp`runtime.startTheWorldWithSema + 640
    frame #4: 0x00000001000452d9 testp`runtime.read + 57
    frame #5: 0x0000000100027cf7 testp`runtime.sigNoteSleep + 71
    frame #6: 0x000000010003eb96 testp`os/signal.signal_recv + 150
    frame #7: 0x000000010006f9b2 testp`os/signal.loop + 34
    frame #8: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #9: 0x0000000100027cf7 testp`runtime.sigNoteSleep + 71
    frame #10: 0x000000010003eb96 testp`os/signal.signal_recv + 150
    frame #11: 0x000000010006f9b2 testp`os/signal.loop + 34
    frame #12: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #13: 0x000000010003eb96 testp`os/signal.signal_recv + 150
    frame #14: 0x000000010006f9b2 testp`os/signal.loop + 34
    frame #15: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #16: 0x000000010006f9b2 testp`os/signal.loop + 34
    frame #17: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #18: 0x00000001000541c1 testp`runtime.goexit + 1
  thread #7
    frame #0: 0x00007fff6af7986a libsystem_kernel.dylib`__psynch_cvwait + 10
    frame #1: 0x00007fff6b03856e libsystem_pthread.dylib`_pthread_cond_wait + 722
    frame #2: 0x0000000100055fe0 testp`runtime.pthread_cond_wait_trampoline + 16
    frame #3: 0x000000010005399d testp`runtime.asmcgocall + 173
    frame #4: 0x0000000100055fd0 testp`runtime.pthread_cond_init_trampoline + 32
    frame #5: 0x0000000100045a09 testp`runtime.pthread_cond_wait + 57
    frame #6: 0x0000000100027a45 testp`runtime.semasleep + 133
    frame #7: 0x000000010000a2f0 testp`runtime.notesleep + 224
    frame #8: 0x000000010002fa30 testp`runtime.stopm + 192
    frame #9: 0x0000000100030b4f testp`runtime.findrunnable + 1343
    frame #10: 0x00000001000317fe testp`runtime.schedule + 702
    frame #11: 0x0000000100031b3d testp`runtime.park_m + 157
    frame #12: 0x00000001000520fb testp`runtime.mcall + 91
    frame #13: 0x0000000100027a45 testp`runtime.semasleep + 133
    frame #14: 0x000000010000a2f0 testp`runtime.notesleep + 224
    frame #15: 0x000000010002fa30 testp`runtime.stopm + 192
    frame #16: 0x0000000100030b4f testp`runtime.findrunnable + 1343
    frame #17: 0x00000001000317fe testp`runtime.schedule + 702
    frame #18: 0x0000000100031b3d testp`runtime.park_m + 157
    frame #19: 0x00000001000520fb testp`runtime.mcall + 91
    frame #20: 0x000000010000a2f0 testp`runtime.notesleep + 224
    frame #21: 0x000000010002fa30 testp`runtime.stopm + 192
    frame #22: 0x0000000100030b4f testp`runtime.findrunnable + 1343
    frame #23: 0x00000001000317fe testp`runtime.schedule + 702
    frame #24: 0x0000000100031b3d testp`runtime.park_m + 157
    frame #25: 0x00000001000520fb testp`runtime.mcall + 91
    frame #26: 0x000000010002fa30 testp`runtime.stopm + 192
    frame #27: 0x0000000100030b4f testp`runtime.findrunnable + 1343
    frame #28: 0x00000001000317fe testp`runtime.schedule + 702
    frame #29: 0x0000000100031b3d testp`runtime.park_m + 157
    frame #30: 0x00000001000520fb testp`runtime.mcall + 91
    frame #31: 0x0000000100030b4f testp`runtime.findrunnable + 1343
    frame #32: 0x00000001000317fe testp`runtime.schedule + 702
    frame #33: 0x0000000100031b3d testp`runtime.park_m + 157
    frame #34: 0x00000001000520fb testp`runtime.mcall + 91
    frame #35: 0x00000001000317fe testp`runtime.schedule + 702
    frame #36: 0x0000000100031b3d testp`runtime.park_m + 157
    frame #37: 0x00000001000520fb testp`runtime.mcall + 91
    frame #38: 0x0000000100031b3d testp`runtime.park_m + 157
    frame #39: 0x00000001000520fb testp`runtime.mcall + 91
    frame #40: 0x00000001000520fb testp`runtime.mcall + 91
    frame #41: 0x00000001000159a3 testp`runtime.runfinq + 163
    frame #42: 0x00000001000541c1 testp`runtime.goexit + 1
    frame #43: 0x00000001000541c1 testp`runtime.goexit + 1
  thread #8
    frame #0: 0x00007fff6af7986a libsystem_kernel.dylib`__psynch_cvwait + 10
    frame #1: 0x00007fff6b03856e libsystem_pthread.dylib`_pthread_cond_wait + 722
    frame #2: 0x0000000100055fe0 testp`runtime.pthread_cond_wait_trampoline + 16
    frame #3: 0x000000010005399d testp`runtime.asmcgocall + 173
    frame #4: 0x0000000100045a09 testp`runtime.pthread_cond_wait + 57
    frame #5: 0x0000000100027a45 testp`runtime.semasleep + 133
    frame #6: 0x000000010000a2f0 testp`runtime.notesleep + 224
    frame #7: 0x000000010002f952 testp`runtime.templateThread + 242
    frame #8: 0x000000010002e6a3 testp`runtime.mstart1 + 195
    frame #9: 0x000000010002e5c6 testp`runtime.mstart + 102
    frame #10: 0x000000010007092d testp`crosscall_amd64 at gcc_amd64.S:35
    frame #11: 0x0000000100070584 testp`threadentry(v=<unavailable>) at gcc_darwin_amd64.c:64:2 [opt]
    frame #12: 0x00007fff6b0352eb libsystem_pthread.dylib`_pthread_body + 126
    frame #13: 0x00007fff6b038249 libsystem_pthread.dylib`_pthread_start + 66
    frame #14: 0x00007fff6b03440d libsystem_pthread.dylib`thread_start + 13

From the backtraces it is clear that the main thread received the SIGPIPE while thread #3 called ProvokeSIGPIPE.

CC @ianlancetaylor: I don't know what to do here. There is SO_NOSIGPIPE but that's only for sockets, not pipes. Should we never forward SIGPIPEs on darwin?

@ianlancetaylor
Copy link
Contributor

The only two options I see are 1) as you suggest, never forward SIGPIPE on macOS; 2) document the problem and move on. If I understand this correctly, the problem can only arise in a C program that calls Go functions. The question is: which choice would be more surprising? Most programmers do not really consider SIGPIPE signals. Most Go programmers in particular do not consider them, as the Go runtime endeavors to do the right thing. So I think option 1 is the best. Happy to hear counter-arguments; I certainly don't feel strongly about it.

@gopherbot
Copy link

Change https://golang.org/cl/188297 mentions this issue: misc/cgo/testcarchive/testdata: test SIGPIPEs on a non-main thread

@bcmills
Copy link
Contributor

bcmills commented Jul 31, 2019

I think we should update the test so that it is not sensitive to this idiosyncrasy, and perhaps update the documentation if we currently make any particular claims about SIGPIPE.

Beyond that, are there any other interactions we should consider? (Did you observe symptoms other than just the test failure?)

@bcmills bcmills added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Darwin labels Jul 31, 2019
@bcmills bcmills added this to the Go1.14 milestone Jul 31, 2019
@ianlancetaylor
Copy link
Contributor

Note that the currrent test is not failing as far as I know.

The question is what to do on macOS if the Go signal handler sees a SIGPIPE that is delivered on a non-Go thread.

@eliasnaur
Copy link
Contributor Author

The current test does not fail because it runs on the main thread. I discovered the non-main thread case as a rare crash in an iOS app put in the background and then resumed. IOS suspends apps in the background and ongoing network connections time out and are closed.

@bcmills
Copy link
Contributor

bcmills commented Jul 31, 2019

I would expect the Go signal handler to forward SIGPIPE based on the program counter that generated the signal rather than the thread that signal was delivered to.

Do we know which fields of the siginfo_t are populated for SIGPIPE on MacOS? (Is it possible that they include some indication of the signal's origin, such as an si_pid or si_fd field?)

@eliasnaur
Copy link
Contributor Author

eliasnaur commented Jul 31, 2019 via email

@gopherbot
Copy link

Change https://golang.org/cl/191785 mentions this issue: runtime: don't forward SIGPIPE on macOS

@ianlancetaylor
Copy link
Contributor

Change was reverted.

tomocy pushed a commit to tomocy/go that referenced this issue Sep 1, 2019
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.

Fixes golang#33384

Change-Id: Ice3de75b121f00006ee11c26d560e619536460be
Reviewed-on: https://go-review.googlesource.com/c/go/+/188297
Run-TryBot: Elias Naur <mail@eliasnaur.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
tomocy pushed a commit to tomocy/go that referenced this issue Sep 1, 2019
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 golang#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: Ian Lance Taylor <iant@golang.org>
t4n6a1ka pushed a commit to t4n6a1ka/go that referenced this issue Sep 5, 2019
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.

Fixes golang#33384

Change-Id: Ice3de75b121f00006ee11c26d560e619536460be
Reviewed-on: https://go-review.googlesource.com/c/go/+/188297
Run-TryBot: Elias Naur <mail@eliasnaur.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
t4n6a1ka pushed a commit to t4n6a1ka/go that referenced this issue Sep 5, 2019
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 golang#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: Ian Lance Taylor <iant@golang.org>
@golang golang locked and limited conversation to collaborators Aug 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Darwin
Projects
None yet
Development

No branches or pull requests

4 participants