Sky凌空
Sky凌空

Reputation: 9

How can I avoid the Opengl crash in mine Snapshot program (Windows)?

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:

  1. Take Snapshot:

    • Freeze all threads → Save thread contexts & TEB → Dump all memory regions → Unfreeze threads.
  2. Restore Snapshot:

    • Freeze all threads → Overwrite memory regions → Restore thread contexts & TEB → Unfreeze threads.

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:

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

Answers (1)

datenwolf
datenwolf

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

Related Questions