Go version
go version go1.22.5 linux/amd64
Output of go env
in your module/workspace:
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/user/.cache/go-build'
GOENV='/home/user/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/user/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/user/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.22.5'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1055368833=/tmp/go-build -gno-record-gcc-switches'
What did you do?
I want to call a userspace program written in go from an LKM. I do this via call_usermodehelper
. However the go program crashes.
You can reproduce it via this simple repository: https://github.com/powellnorma/go-crash
Any workarounds? Thank you.
What did you see happen?
runtime: epollwait on fd 1 failed with 22
fatal error: runtime: netpoll failed
runtime stack:
runtime.throw({0x4985aa?, 0x7ffcafbcd088?})
/usr/local/go/src/runtime/panic.go:1077 +0x5c fp=0x7ffcafbcd010 sp=0x7ffcafbccfe0 pc=0x430b1c
runtime.netpoll(0xc000006d00?)
/usr/local/go/src/runtime/netpoll_epoll.go:122 +0x34a fp=0x7ffcafbcd6a0 sp=0x7ffcafbcd010 pc=0x42d32a
runtime.startTheWorldWithSema()
/usr/local/go/src/runtime/proc.go:1438 +0x37 fp=0x7ffcafbcd700 sp=0x7ffcafbcd6a0 pc=0x435dd7
runtime.gcStart.func3()
/usr/local/go/src/runtime/mgc.go:749 +0x25 fp=0x7ffcafbcd728 sp=0x7ffcafbcd700 pc=0x415ec5
traceback: unexpected SPWRITE function runtime.systemstack
runtime.systemstack()
/usr/local/go/src/runtime/asm_amd64.s:509 +0x4a fp=0x7ffcafbcd738 sp=0x7ffcafbcd728 pc=0x45ac2a
goroutine 1 [running]:
runtime.systemstack_switch()
/usr/local/go/src/runtime/asm_amd64.s:474 +0x8 fp=0xc00005cba0 sp=0xc00005cb90 pc=0x45abc8
runtime.gcStart({0xc000500000?, 0x4a000?, 0x49fa0?})
/usr/local/go/src/runtime/mgc.go:748 +0x3fc fp=0xc00005cc38 sp=0xc00005cba0 pc=0x415d3c
runtime.mallocgc(0x49fa0, 0x48d1c0, 0x1)
/usr/local/go/src/runtime/malloc.go:1242 +0x76f fp=0xc00005cca0 sp=0xc00005cc38 pc=0x40bbaf
runtime.newarray(0x8?, 0xc00005cce8?)
/usr/local/go/src/runtime/malloc.go:1346 +0x45 fp=0xc00005ccc8 sp=0xc00005cca0 pc=0x40be25
[..]
What did you expect to see?
No crash.
Comment From: ianlancetaylor
It looks like when the kernel module runs the Go program, it runs it with (at least) file descriptor 1 not set to standard output. One effect is that the netpoll code uses descriptor 1 for the epoll descriptor. The program then uses Dup2
to clobber that descriptor.
There is no nothing we can change in Go to fix this, so closing this issue.
Comment From: powellnorma
Thank you for investigating. Does that mean it is not possible from within go to set the file descriptors 0-2 before the go runtime uses them? Wouldn't that mean that even when I don't change what FD 1 refers to (via Dup2
) that it e.g. fmt.Printf
would print to a FD its not supposed to interact/interfere with (the epoll FD)?
I guess in that case a workaround would be to write a wrapper program that sets those FDs before executing the application written in go.
Comment From: powellnorma
And what would be the best way to check for this situation? I could check if /proc/self/fd/1
points to anon_inode:[eventpoll]
.. But is there something more elegant?
Comment From: ianlancetaylor
The Go os package on Unix systems does expect that it will be started with file descriptors 0, 1, and 2 set as they normally are. There is no support for programs that use the os package to run without those descriptors being set.
I don't know of a fully reliable way to detect the situation. It may work to syscall.Fstat
descriptors 0, 1, and 2 and verify that they are all regular files or pipes.