go x/exp/shiny: Windows上的内存损坏

wyyhbhjk  于 6个月前  发布在  Go
关注(0)|答案(6)|浏览(42)

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

$ go version
go version go1.17 windows/amd64

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

是的。

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

go env 输出

$ go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=%LocalAppData%\go-build
set GOENV=%AppData%\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\dev\lang\go_path\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\dev\lang\go_path
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\dev\lang\go\1.17
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\dev\lang\go\1.17\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.17
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=NUL
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\dev\cygwin64\tmp\go-build1333133088=/tmp/go-build -gno-record-gcc-switches

你做了什么?

https://gist.github.com/theinternetftw/95151dd990fe955644275e13993ef69e

你期望看到什么?

永远看不到"内存损坏!" Println

你看到了什么?

"内存损坏" Println 经常出现。(在我实际程序中的大切片内存损坏也是如此)

讨论

我通过让shiny不在主os线程之外调用SendMessage来解决这个问题。
我在自己修复后停止了主要调查,没有再看到任何复发,但对于可能导致其发生的原因有一些想法可能有所帮助:

  • 或许某种方式等待SendMessage涉及到特定的窗口时会导致损坏,或者当SendMessage花费一些时间返回结果时。
  • 可能与主驱动线程永久抓住os线程锁有关,但是当使用syscall.Syscall家族的函数时, lockOSThread is nonetheless called later
bwitn5fc

bwitn5fc1#

批处理文件版本如下:
@theinternetftw 非常感谢您的指导。的确,我可以重现您的问题。
不幸的是,我不知道问题是什么,所以留给大家决定在这里应该采取什么行动。
Alex

ufj5ltwl

ufj5ltwl2#

可能相关的是,操作系统线程锁被主驱动线程永久性地抓住了,但是当使用syscall.Syscall系列函数时,lockOSThread仍然会被调用。
lockOSThread将goroutine锁定到当前的操作系统线程,这不一定是主线程。因此,在syscall.Syscall周围使用lockOSThread并不能保证syscall是在主线程上执行的。

a6b3iqyw

a6b3iqyw3#

cc @nigeltao
cc @alexbrainman@bufflig for Windows.

mklgxw1f

mklgxw1f4#

我对于Windows编程的一般情况和SendMessage具体内容了解不多,所以我将这个留给其他人。

wnvonmuf

wnvonmuf5#

@theinternetftw
我使用当前的Go主仓库和golang.org/x/exp的最新版本构建了你的程序。我运行了你的程序20次,但一次都没看到打印出memory corruption的消息。
我做错了什么?
谢谢。
Alex

dnph8jn4

dnph8jn46#

在代码顶部有一个注解,显示了一个脚本,用于在循环中不断重启程序,直到出现错误。正是通过使用这样的脚本,才花了大约一分钟触发了这个bug。

在那条评论中,我给出了一个bash脚本,用于在循环中运行程序(我使用的是cygwin)。批处理文件版本如下:

@echo off
:loop
.\repro.exe
if %errorlevel% == 1 (exit)
goto loop

今天,在两台不同的计算机(都是Windows 10版本19042.1165)上,在使用gotip编译后,它打印消息的速度最快为2秒,最慢为5分50秒,平均约为3分钟。比我在最初发布这个bug之前测试它时慢了好几倍,原因不明。

(编辑:我在这里有一个关于触发bug更快的重现代码版本的段落,但我刚刚发现,在同一台计算机上,它可以在10秒内可靠地触发bug,而在另一台计算机上,它根本没有更快地触发bug。我会把它留在这里以供参考,但它可能对你也可能对你没有用:http://theinternetftw.com/code/shinyrepro2.zip)

祝好!

相关问题