运行某个程序的特定开发版本时,我偶尔会遇到挂起,而使用官方版本似乎不会挂起。开发版本的不同之处主要在于它引入了更多的 Go std 库,(大部分)它没有使用;所以可执行文件更大,加上 static-var 和 init() 初始化已完成,这可能会增加遇到某些竞争条件的可能性。git bisect run将(golang)的罪魁祸首确定为6becb033341602f2df9d7c55cc23e64b925bbee2:Author: Ian Lance Taylor <iant@golang.org>Date: Thu Apr 11 16:53:11 2019 -0700[...] runtime: switch to using new timer codediff --git a/src/runtime/time.go b/src/runtime/time.goindex fea5d6871c..db48a932d4 100644--- a/src/runtime/time.go+++ b/src/runtime/time.go@@ -14,7 +14,7 @@ import ( ) // Temporary scaffolding while the new timer code is added.-const oldTimers = true+const oldTimers = false // Package time knows the layout of this structure. // If this struct changes, adjust ../time/sleep.go:/runtimeTimer.浏览了这个小改动带来的差异后,我强烈倾向于在这个“新计时器代码”和/或它启用的代码中存在一些竞争条件。无论是通过 Ctrl-\ ( SIGQUIT ) 还是delve attach,罪魁祸首似乎总是cmd.Start()这里的调用:func sh(dir string, stdin io.Reader, stdout io.Writer, stderr io.Writer, name string, args []string) Object {cmd := exec.Command(name, args...)cmd.Dir = dircmd.Stdin = stdinvar stdoutBuffer, stderrBuffer bytes.Bufferif stdout != nil { cmd.Stdout = stdout} else { cmd.Stdout = &stdoutBuffer}if stderr != nil { cmd.Stderr = stderr} else { cmd.Stderr = &stderrBuffer}err := cmd.Start()PanicOnErr(err)从那里开始的堆栈跟踪看起来非常相似,直到到达syscall/exec_unix.go(在 Go 源代码树中)。然后,在 Delve 中,似乎挂起的是forkAndExecInChild()调用,而 Ctrl-\ 将readlen()调用显示为挂起:// Kick off child.pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])if err1 != 0 { err = Errno(err1) goto error}ForkLock.Unlock()// Read child error status from pipe.Close(p[1])n, err = readlen(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))Close(p[0])if err != nil || n != 0 {forkAndExecInChild()代码似乎挂在,这是一个循环内exec_darwin.go:206的系统调用。libc_dup2_trampoline假设这只是对 的调用dup2(),我想不出它会挂起的任何原因;但是我已经“捕获”了一个挂起的测试运行在那里(并且没有其他地方)至少两次, via delve,尽管这可能只是使用delve attach <pid> ...与 Ctrl-\ (SIGQUIT)的产物?
1 回答
DIEA
TA贡献1820条经验 获得超2个赞
这是 Go for MacOS 上的一个错误,已在https://go-review.googlesource.com/c/go/+/372798/中得到修复
对于修复之前受影响的 Go 版本,解决方法是传递-Wl,-bind_at_load
给链接器,这可以通过调用 go with-ldflags="-extldflags=-Wl,-bind_at_load"
- 1 回答
- 0 关注
- 131 浏览
添加回答
举报
0/150
提交
取消