Reputation: 9
I'm attempting to implement process snapshot functionality in C++ on Windows x64, aiming to save a process's runtime state and restore it after a certain period while keeping the process running. My goal is to accomplish all operations in user mode whenever possible.
Currently, I specifically save the process's memory, all thread contexts, and TEB (Thread Environment Block) for restoration. This works correctly with older programs like Minesweeper, Plants vs. Zombies, and custom command-line applications.
However, when handling OpenGL-based graphical rendering program, the restoration often fails, causing crashes in nvoglv64.dll with error codes 0xc0000409 and 0xc0000005. I tried skipping memory regions associated with this module, but the errors persist.
My workflow:
Take Snapshot:
Restore Snapshot:
Analysis:
The issue likely stems from OpenGL storing resource handles (e.g., textures, buffers) in GPU memory (VRAM). These GPU-specific states aren’t captured during the process snapshot, leading to state inconsistencies upon restoration. While VRAM isn’t directly accessible, I hypothesize that GPU state preservation might require indirect methods like process injection or DLL forwarding. I attempted these approaches but lack sufficient knowledge of rendering engine internals to resolve the issue.
How can I solve the crash problem? Relevant Details:
Program: Snapshot.exe (automatically snapshots a process named test.exe and restores it 4 seconds later).
A crash dump (.dmp) from the failing program is available.
Error Stack
nvoglv64!vk_icdNegotiateLoaderICDInterfaceVersion+0xcade5
nvoglv64!DrvValidateVersion+0xaa0a
nvoglv64!DrvPresentBuffers+0x2acd7
nvoglv64!DrvPresentBuffers+0x2a217
nvoglv64!DrvPresentBuffers+0x188b3
nvoglv64!DrvPresentBuffers+0x1302c2
nvoglv64!DrvPresentBuffers+0x132598
nvoglv64!DrvPresentBuffers+0x13478d
nvoglv64!DrvPresentBuffers+0x13338b
nvoglv64!DrvPresentBuffers+0x14d9d8
nvoglv64!DrvValidateVersion+0x6c76
nvoglv64!DrvPresentBuffers+0x112ca1
nvoglv64!DrvPresentBuffers+0xc9218
nvoglv64!DrvPresentBuffers+0xef6f2
nvoglv64!DrvPresentBuffers+0xef00d
nvoglv64!DllMain+0x7d46
nvoglv64!DllMain+0x7ebd
nvoglv64!DllMain+0x7c9e
nvoglv64!DllMain+0x760e
nvoglv64!DrvSwapLayerBuffers+0x2b6
nvoglv64!DllMain+0xa683
nvoglv64+0x11133a3
nvoglv64+0x1113087
nvoglv64!DrvValidateVersion+0xd988
kernel32!BaseThreadInitThunk+0x14
ntdll!RtlUserThreadStart+0x21
Upvotes: -2
Views: 60
Reputation: 162297
You're trying to do something, that's impossible without the help from the kernel and its driver infrastructure. OpenGL is not an engine, it's a driver API. And much of the internal state of the OpenGL ICD loaded into the process are tied to hardware and kernel driver state. So even if you manage to restore a perfect process image, including all user facing handles, you can't restore the in-kernel structures tied to it.
Much of the kernel side internal state is inaccessible to user space, yet intricately intertwined with the state of the process. Take coherently mapped OpenGL buffer objects for example: Those map a portion of OpenGL memory, usually living on the GPU, into the process's address space. Writes to these locations usually go to the GPU. However the OpenGL implementation may decide – for example in low memory conditions – to also keep a shadow copy in system RAM for eviction. There is no control whatsoever, where in address space those mappings are established; there's no way to map to a fixed address, or even make a suggestion as you'd do with the lpBase
parameter of MapViewOfFileEx
.
Upvotes: 0