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/race: some kind of fork/exec deadlock? #4840
Labels
Comments
Here's a complete trace. I ABRTed the child process first. The parent seemed stuck doing a bunch of sched_yield system calls, so I ABRTed that next. It seems to have gotten stuck in a slightly different place as before, but it looks like the same issue. You'll see that my build steps are: ./make.bash go install -v -race std so I think I actually end up with a race-enabled go command, which might be a bit different from what normal people work with daily. That explains the tsan stuff in the stack traces. So this might actually be a race detector issue. Attachments:
|
(gdb) thread apply all bt Thread 1 (process 2399): #0 0x00007f7e1cd296ac in __lll_lock_wait_private () from /lib64/libc.so.6 #1 0x00007f7e1ccafa0f in _L_lock_10695 () from /lib64/libc.so.6 #2 0x00007f7e1ccad587 in malloc () from /lib64/libc.so.6 #3 0x000000000047eaf4 in __sanitizer::InternalAlloc(unsigned long) () #4 0x00007f7de40b0a68 in ?? () #5 0x0000000000481e42 in __tsan::StackTrace::ObtainCurrent(__tsan::ThreadState*, unsigned long) () #6 0x00007f7de40b0a08 in ?? () #7 0x00007f7de40b3240 in ?? () #8 0x0000000000000005 in ?? () #9 0x0000000000481ee1 in __tsan::TraceSwitch(__tsan::ThreadState*) () #10 0x00007f7dd57f9e00 in ?? () #11 0x00007f7de40b0a08 in ?? () #12 0x00007f7de40b0a08 in ?? () #13 0x0094000000a00000 in ?? () #14 0x0094000000a00001 in ?? () #15 0x00000000004887a7 in __tsan_read () #16 0x00000000005a8b2c in syscall.forkAndExecInChild (fp=6171101, argv0=0xc2008a9800 "", argv= []*uint8, envv= []*uint8, chroot=0x7f7dd57fa700 "", dir=0x0, attr=0x0, sys=0x0, pipe=0, pid=140179631511840, err=0) at /build/go.tip/go/src/pkg/syscall/exec_linux.go:52 #17 0x00000000005e29dd in threadentry () #18 0x000000c2008a9800 in ?? () #19 0x000000c200a2c300 in ?? () #20 0x0000000000470690 in ?? () at /build/go.tip/go/src/pkg/runtime/proc.c:772 #21 0x0000000000000000 in ?? () |
Thanks! It helps! It's indeed fork/exec deadlock caused by tsan. The problem is that between fork and exec, one can do only very limited set of things. And tsan does prohibited things, i.e. calls malloc()... and apparently the child was forked with taken malloc mutex. Labels changed: added racedetector. Owner changed to @dvyukov. |
Yes, I was able to reproduce it by running "GOMAXPROCS=82 go test -run=noneasd std" repeatedly, but it required about 50 runs. The simplest solution would be to not instrument that piece of code between fork and exec. But I am not sure how to do it, currently we don't have such general facility. Perhaps hack go/gc to ignore a specific file in syscall package. |
It become worser with preemption. Now forkAndExecInChild() calls runtime.Gosched() after fork()... goroutine 5 [runnable]: runtime/race.Write(0x1f63308, 0xc2100e43d0, 0x5ad9be) runtime/race/_obj/race.cgo1.go:55 runtime.racewrite(0xc2100e43d0, 0x0, 0x0, 0x0, 0x0, ...) src/pkg/runtime/race.c:75 +0x67 syscall.forkAndExecInChild(0xc2100cc940, 0xc2100cca80, 0x7, 0x7, 0xc210135300, ...) src/pkg/syscall/exec_linux.go:58 +0x22e syscall.forkExec(0xc2100cc9c0, 0x3e, 0xc2100f12a0, 0x6, 0x6, ...) src/pkg/syscall/exec_unix.go:191 +0x596 syscall.StartProcess(0xc2100cc9c0, 0x3e, 0xc2100f12a0, 0x6, 0x6, ...) src/pkg/syscall/exec_unix.go:238 +0x84 os.startProcess(0xc2100cc9c0, 0x3e, 0xc2100f12a0, 0x6, 0x6, ...) src/pkg/os/exec_posix.go:45 +0x547 os.StartProcess(0xc2100cc9c0, 0x3e, 0xc2100f12a0, 0x6, 0x6, ...) src/pkg/os/doc.go:24 +0x6c |
I want to change 6g so that it does not instrument files containing syscall.forkAndExecInChild() functions. Any objections? In C/C++ land we mark functions that call fork with __attribute__((no-thread-safety-analysis)) or use separate instrumentation blacklists. But I think it's too early for such general solution in Go. |
To clarify, you want to change the behaviour on specific files within a package? That is, when compiling the syscall package, you want to compile some files with -race and some without? Further, do you really care about the file level? Would it suffice to compile some functions with -race and some without? Note that we already have a precedent for comments that are specific to functions, such as //go:noescape. It seems that it would not be out of the question to have a //go:norace comment. |
> To clarify, you want to change the behaviour on specific files within a package? Yes. I don't have strong opinion on files vs functions yet. Function level is probably better. Because the next time we may need to not instrument only a single function in a large file. I will look how //go:noescape is implemented. If most of the machinery for such attributes is already there, and I just need to add one more attribute, then it looks like a good choice. |
Mailed https://golang.org/cl/10783043 with go:norace |
This issue was closed by revision 63e0ddc. Status changed to Fixed. |
This issue was closed.
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
The text was updated successfully, but these errors were encountered: