排查和解决Unity 2018.3.6f1的“GetThreadContext failed”错误

公司的项目需要使用Unity 2018.3.6f1,但是在开启杀毒软件(360安全卫士、Windows Defender或Avast等等)时,或者通过TeamViewer为客户远程演示产品功能时,会频繁出现“GetThreadContext failed”错误,如下图所示:

GetThreadContext失败错误

在谷歌上搜索了很长时间,才在Unity官方论坛上找到一个有价值的帖子:
https://forum.unity.com/threads/unity-4-0-1f2-and-avast-8-0-1482-getthreadcontextfailed-error.172759/

在这篇帖子里,很多用户使用Avast杀毒软件,导致频繁出现“GetThreadContext failed”错误,根据Unity大佬的分析,这是由于老版本的Mono在内存垃圾回收时存在线程安全的bug而导致的,大佬分析的回帖如下图所示:

bug原因分析

Unity在发生此类错误而崩溃时,会生成crash.dmp文件,存放在C:\Users\ghoul\AppData\Local\Temp\PanoSim2019\Unity\Crashes目录中。使用WinDbg工具打开crash.dmp文件,运行!analyze -v命令,分析崩溃转储文件,可以看到异常堆栈,如下图所示:

异常堆栈信息

根据异常堆栈,可以确定是mono_2_0_bdwgc.dll动态链接库出了问题,而这个动态库正是Boehm-Demers-Weiser垃圾回收器的一个实现!去Unity-Technologies的mono代码仓库搜索一下,发现这个垃圾回收器的bug在2019年2月份修复了,如下图所示:

bdwgc的缺陷修复记录

接下来,我们要自己编译新版的Mono源码,然后提取mono_2_0_bdwgc.dll文件,应该就能解决问题了!

在D盘根目录打开Git Bash,然后下载Mono代码仓库和子模块:

git clone --recursive https://github.com/Unity-Technologies/mono.git

注意,GitHub的下载速度极慢,可以参考《如何为Git设置代理》设置代理进行下载,整个源码库约有2.5GB。

Mono最低需要Visual Studio 2017才能编译,而我电脑上安装的是Visual Studio 2019,在打开msvc解决方案时,需要将Windows SDK从8.1升级成10。打开Visual Studio 2019,在其中打开mono源码目录中的msvc\mono.sln文件,此时便能看到检查解决方案的窗口,提示需要重新定向SDK工具集,如下图所示:

在VS2019中检查mono解决方案

点击“确定”按钮,升级平台工具集。然后,将解决方案配置设成“Release”,将解决方案平台设成“x64”,最后在解决方案资源管理器中,右键点击mono解决方案,在菜单中选择“生成解决方案”,即可编译mono。编译完成之后,在mmsvc\build\bdwgc\x64\bin\Release目录中可以找到编译的mono_2_0_bdwgc.dll文件,如下图所示:

获取编译的dll文件

最后,用编译得到的“mono_2_0_bdwgc.dll`替换Unity 2018.3.6f1中的文件即可解决问题!