Does unix.Pipe/Select + goroutines requires some particular care?

69 views
Skip to first unread message

c.maglie

unread,
Apr 5, 2022, 1:00:14 PM4/5/22
to golang-nuts

Hi,

I'm facing an issue that looks like a deadlock, but that I can't
actually figure out. After some investigation I can reproduce a similar
problem with the following code:

https://go.dev/play/p/ZB05nweJJX_9

Running the example above as-is will show the expected output, but after
uncommenting the time.Sleep inside the goroutine (so it executes after
the "Select") then everything locks out.

Is there a way to avoid this behaviour?

Thank you,

C

Ian Lance Taylor

unread,
Apr 5, 2022, 1:10:44 PM4/5/22
to c.maglie, golang-nuts
It works fine for me either way, on Linux kernel 5.15.15. What system
are you running on? What version of Go? What version of
golang.org/x/sys/unix?

Ian

c.maglie

unread,
Apr 5, 2022, 8:05:37 PM4/5/22
to golan...@googlegroups.com
Il 05/04/22 19:09, Ian Lance Taylor ha scritto:
> It works fine for me either way, on Linux kernel 5.15.15. What system
> are you running on? What version of Go? What version of
> golang.org/x/sys/unix?

Well, I tried it only on the playgound because it seems to reproduce the
bug there, so I didn't bother to try on my machine.
Now I tried and indeed it runs fine for me too (linux 4.15.0 - go 1.18).

BTW even if the trimmed-down example seems to work fine (at least
outside of the playground) I still see the bug in my full project, it is
composed of many pieces that needs to run together to actually reproduce
it, it's a bit hard to post here. :-(

I tried to pprof the application, and this is the state when it locks
https://pastebin.com/raw/L1wa5hz6 basically everything is waiting on
mutex, except the last goroutine that is trying to do a unix.Close(..)
(and it is supposed to unlock everything else when done, but it's
blocked for some reason an it never returns).

syscall.Syscall+0x4 go1.18/src/syscall/asm_linux_amd64.s:20
/sys/unix.Close+0x2f
go/pkg/mod/golang.org/x/s...@v0.0.0-20220405052023-b1e9470b6e64/unix/zsyscall_linux.go:571

this is the version of x/sys:

golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64 // indirect

C

Ian Lance Taylor

unread,
Apr 5, 2022, 8:14:39 PM4/5/22
to c.maglie, golan...@googlegroups.com
It's hard to see why a call to unix.Close would block.

The only possibility that comes to mind is that perhaps the garbage
collector is trying to stop all goroutines, which it needs to do
briefly during a complete GC cycle. If there some thread that is not
listening to the GC, then it is possible for unix.Close to wait for
the GC which is waiting for that other thread. If you can get a
goroutine stack dump, you might see this as some thread sitting in
RawSyscall. Or it might happen if you are doing something unsupported
with go:linkname to call C functions directly rather than via cgo.

It may possibly help to run the program under "strace -f" to see which
system calls are blocking at the point where the program hangs.

Sorry this isn't much help.

Ian
Reply all
Reply to author
Forward
0 new messages