go x/mobile:当发生恐慌时,足够长的回溯会导致Android上的运行时死锁,

enyaitl3  于 2个月前  发布在  Go
关注(0)|答案(7)|浏览(28)

你使用的Go版本是什么( go version )?

$ go version
go version go1.13.1 linux/amd64

这个问题在最新版本的发布中是否重现?

是的。

你正在使用什么操作系统和处理器架构( go env )?

go env 输出

$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home//.cache/go-build"
GOENV="/home//.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/opt/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/lib/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
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 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build557544076=/tmp/go-build -gno-record-gcc-switches"

你做了什么?

我有一个使用gomobile编译的Go应用程序,用于Android。当发生panic时,运行时会打印一个回溯并退出。然而,当这个回溯足够长时,应用程序冻结且永远不会退出。
Gomobile将 stderr 重定向到Android(Android日志标签为“GoLog”)。当发生panic时,世界冻结,因此:

  • goroutine lineLog 不再消耗连接到 dup 的管道;
  • 在某个时刻,管道变得满;
  • 运行时继续在 stderr 中写入长的回溯并阻塞,直到 stderr 可写;
  • 死锁。

禁用gomobile从 stderr 的重定向使应用程序以“正确”的方式崩溃。
请注意,运行时已经将日志重定向到Android(带有标签“Go”),因此我认为gomobile的 stderr 重定向似乎是多余的?
要重现问题,你可以修改运行时,在捕获到panic时增加很多行,直到运行时冻结。

你期望看到什么?

当发生panic时,如果产生的回溯足够长,我希望运行时能打印完整的回溯并退出。

你看到了什么?

当发生panic时,如果产生的回溯足够长,我看到的是运行时打印了一个截断的回溯并冻结。

rqqzpn5f

rqqzpn5f1#

@eliasnaur,我知道你不再维护它了,但如果现在内置的Go支持能够使gomobile移除这个位,那将是很好的。或者还有其他原因导致它存在?

brqmpdu1

brqmpdu12#

据我所知,运行时只会将其自身的打印(崩溃信息)重定向到stderr。gomobile重定向是针对所有写入到stderr(以及stdout)的操作,而不仅仅是运行时的。
一个解决方法是用C(go)重写gomobile重定向。

yvgpqqbh

yvgpqqbh4#

另一个想法是实现一个缓冲写入器,只替换 os.Stdout/Stderr 。这不会重定向所有的标准输出/错误日志,但Go代码会很好,而且标准错误不会被复制,所以转储会起作用。

8ulbf1ek

8ulbf1ek5#

想知道是否可以让gomobile直接使用类似于runtime/write_err_android.go的代码将所有日志发送到logd。更理想的是,如果它允许用户打开和关闭,那就太好了——我发现一些库的日志记录对于移动应用程序的使用场景来说太过冗长了。

ycl3bljg

ycl3bljg6#

针对这个问题的提议补丁:golang/mobile#40

u91tlkcl

u91tlkcl7#

https://golang.org/cl/212839提到了这个问题:internal/mobileinit: redirect std{out,err} without using Go

相关问题