-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Closed
Labels
FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.The path to resolution is known, but the work has not been done.
Milestone
Description
What version of Go are you using (go version)?
$ go version go version go1.12.4 linux/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 GOARCH="amd64" GOBIN="" GOCACHE="/root/.cache/go-build" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOOS="linux" GOPATH="/root/go" GOPROXY="" GORACE="" GOROOT="/usr/lib/golang" GOTMPDIR="" GOTOOLDIR="/usr/lib/golang/pkg/tool/linux_amd64" GCCGO="gccgo" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="" 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=/tmp/go-build326439240=/tmp/go-build -gno-record-gcc-switches"
What did you do?
Go program uses cgo. C part of program creates 2 threads by pthread_create: event_loop and watchdog(for monitoring hanged event loop). C code doesn't install any signal handlers and doesn't change sigmask.
C-code calls go-code for logging.
Simple C code of watchdog thread that uses popen/pclose and generates SIGCHLD signals:
static void dump_os_state(void)
{
FILE *fp = popen("ps axv", "re");
if (fp) {
dump_to_log(fp); // call go code for logging
pclose(fp);
}
}
static void do_monitor(struct pcs_evloop *evloop, struct pcs_watchdog *proc_wd, abs_time_t now)
{
// if event loop thread was inactive for a long period than dump stack and list of processes into log
dump_kstack(evloop);
dump_os_state();
}
static pcs_thread_ret_t watchdog_thread(void * arg)
{
struct pcs_process *proc = arg;
struct pcs_watchdog *wd = proc->evloops[0].wd;
while (wd->run) {
u32 i;
for (i = 0; i < proc->nr_evloops; i++)
do_monitor(&proc->evloops[i], wd, last);
}
return 0;
}
Backtrace of deadlock:
(gdb) bt #0 runtime.osyield () at /usr/lib/golang/src/runtime/sys_linux_amd64.s:627 #1 0x000000000043adf4 in runtime.lockextra (nilokay=false, ~r1=) at /usr/lib/golang/src/runtime/proc.go:1754 #2 0x000000000043a88d in runtime.needm (x=) at /usr/lib/golang/src/runtime/proc.go:1566 #3 0x000000000044ba57 in runtime.badsignal (sig=17, c=0x7f844d3de6d8) at /usr/lib/golang/src/runtime/signal_unix.go:594 #4 0x000000000044b2d0 in runtime.sigtrampgo (sig=, info=0x7f844d3de8b0, ctx=0x7f844d3de780) at /usr/lib/golang/src/runtime/signal_unix.go:299 #5 0x0000000000466c23 in runtime.sigtramp () at /usr/lib/golang/src/runtime/sys_linux_amd64.s:357 #6 signal handler called #7 runtime.muintptr.ptr (mp=824635164416, ~r0=) at /usr/lib/golang/src/runtime/runtime2.go:241 #8 0x000000000043a8bc in runtime.needm (x=) at /usr/lib/golang/src/runtime/proc.go:1577 #9 0x0000000000464887 in runtime.cgocallback_gofunc () at /usr/lib/golang/src/runtime/asm_amd64.s:712 #10 0x000000000046483e in runtime.cgocallback () at /usr/lib/golang/src/runtime/asm_amd64.s:684 #11 0x000000000065efd6 in _cgoexp_cd95bf089ac7_goLogHandler (a=0x7f844d3df590, n=24, ctxt=0) at _cgo_gotypes.go:294 #12 0x00000000005e4317 in crosscall2 () at /usr/lib/golang/src/runtime/cgo/asm_amd64.s:59 #13 0x0000000000af2ae0 in goLogHandler (p0=1295905936, p1=0x7f844d3df710 " PID TTY STAT TIME MAJFL TRS DRS RSS %MEM COMMAND\n", p2=64) at _cgo_export.c:38 #14 0x00007f8457c10080 in log_print_buf (level=level@entry=0, buf=buf@entry=0x7f844d3df710 " PID TTY STAT TIME MAJFL TRS DRS RSS %MEM COMMAND\n", len=64, skiplock=skiplock@entry=0) at log.c:597 #15 0x00007f8457c120a7 in pcs_valog (level=0, prefix=prefix@entry=0x0, fmt=fmt@entry=0x7f8457c37cd0 "%s", va=va@entry=0x7f844d3dfb60) at log.c:978 #16 0x00007f8457c122b3 in pcs_log (level=level@entry=0, fmt=fmt@entry=0x7f8457c37cd0 "%s") at log.c:999 #17 0x00007f8457c176e3 in dump_kstack (evloop=) at pcs_watchdog.c:82 #18 0x00007f8457c17821 in do_monitor (evloop=) at pcs_watchdog.c:101 #19 watchdog_thread (arg=0x7f84400008e0) at pcs_watchdog.c:116 #20 0x00007f84575afe65 in start_thread (arg=0x7f844d3e0700) at pthread_create.c:307 #21 0x00007f84572d888d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
What did you expect to see?
Successful execution of cgo callback.
What did you see instead?
The execution got stuck into an infinite loop in runtime.lockextra.
What happened:
- C-code wanted to log string and called go-code
- cgocallback called needm and took lock in lockextra
- signal handler called before unlockextra in needm function (received SIGCHLD from C thread from popen)
- badsignal from sigtrampgo also called needm function and got stuck into infinite loop in lockextra
Looks like there is a deadlock when signal raised in section between lockextra/unlockextra.
So is it a valid bug or I've violated some cgo rules? I've found #34391 issue but looks like root cause is different.
Metadata
Metadata
Assignees
Labels
FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.The path to resolution is known, but the work has not been done.