Skip to content

msvc闪退与修复std::mute重入 #9

Description

@lsz7575

deepseek修的
修改文件 html_impl_vklayer.cpp
190行
// NOTE: the caller (setDeviceDataQueues) must already hold gMutex.
QueueData *queueData = &gQueueData[queue];
queueData->device = deviceData;
822行
// Store the table and related VkQueue.
std::lock_guardstd::mutex lock(gMutex);
// NOTE: don't call getDeviceData() here - it would lock gMutex again.
DeviceData *deviceData = &gDeviceData[*pDevice];
deviceData->deviceTable = deviceTable;

崩溃根因
用 cdb 启动 Sky.exe 抓到崩溃现场:

异常:C++ EH exception - code e06d7363 (!!! second chance !!!)
崩溃栈关键帧:
复制
WINHTTP!std::_Mutex_base::lock
WINHTTP!std::lock_guardstd::mutex::lock_guardstd::mutex
WINHTTP!HT_vkCreateDevice → getDeviceData...
日志最后停在 Initialized mod HT's Mod Loader.,之后游戏初始化 Vulkan、创建 VkDevice 时崩。
根因在 src/backends/html_impl_vklayer.cpp:

cpp
复制
// HT_vkCreateDevice 内
std::lock_guardstd::mutex lock(gMutex);
DeviceData *deviceData = getDeviceData(*pDevice); // ← getDeviceData 内部又 lock gMutex!
getDeviceData 内部是:

cpp
复制
static DeviceData *getDeviceData(VkDevice device) {
std::lock_guardstd::mutex lock(gMutex); // 同一线程重入 lock
return &gDeviceData[device];
}
同样的问题还有 createQueueData(持锁后调 getQueueData)。

MSVC 的 std::mutex 对同一线程重复 lock 会直接抛 std::system_error(e06d7363),异常无人捕获 → 进程崩溃闪退。
MinGW 的 win32 线程模型 mutex 可重入,所以同一份代码 MinGW 编译出来正常,MSVC 编译出来闪退。

已修复
改了两处,持锁路径直接访问 map,不再调用带锁的 helper:

cpp
复制
DeviceData *deviceData = &gDeviceData[*pDevice]; // HT_vkCreateDevice 内,已持锁
QueueData *queueData = &gQueueData[queue]; // createQueueData 内,调用者已持锁
已重新编译并验证
已用 MSVC Release 重新编译,winhttp.dll 已输出到 Z:\Sky\winhttp.dll(并同步到 msvcbuild\dist\Release\)。
cdb 再跑一次:日志已经走到之前到不了的位置:
复制
[INFO] Initialized mod HT's Mod Loader.
[INFO] Enabled mod HT's Mod Loader.
过了崩溃点,不再闪退。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions