@@ -307,32 +307,47 @@ void pushContext(std::function<void()> callbackFunction, bool drawDefaultUI) {
307307
308308 // Re-enter main loop until the context has been popped
309309 size_t currentContextStackSize = contextStack.size ();
310- while (contextStack.size () >= currentContextStackSize) {
311310
312- sleepForFramerate ();
313- mainLoopIteration ();
314-
315- // auto-exit if the window is closed
316- if (render::engine->windowRequestsClose ()) {
317- popContext ();
311+ // Helper lambda to perform cleanup of the context
312+ auto cleanupContext = [&]() {
313+ // Restore the previous context, if there was one
314+ if (!contextStack.empty ()) {
315+ ImGui::SetCurrentContext (contextStack.back ().context );
316+ ImPlot::SetCurrentContext (contextStack.back ().plotContext );
317+ render::engine->updateImGuiContext (newContext, &newIO, oldContext, &oldIO);
318+ ImGuizmo::PopContext ();
318319 }
319- }
320320
321- // Restore the previous context, if there was one
322- if (!contextStack.empty ()) {
323- ImGui::SetCurrentContext (contextStack.back ().context );
324- ImPlot::SetCurrentContext (contextStack.back ().plotContext );
325- render::engine->updateImGuiContext (newContext, &newIO, oldContext, &oldIO);
326- ImGuizmo::PopContext ();
321+ // WARNING: code duplicated here and in screenshot.cpp
322+ // Workaround overzealous ImGui assertion before destroying any inner context
323+ // https://github.com/ocornut/imgui/pull/7175
324+ newIO.BackendPlatformUserData = nullptr ;
325+ newIO.BackendRendererUserData = nullptr ;
326+ ImPlot::DestroyContext (newPlotContext);
327+ ImGui::DestroyContext (newContext);
328+ };
329+
330+ try {
331+ while (contextStack.size () >= currentContextStackSize) {
332+
333+ sleepForFramerate ();
334+ mainLoopIteration ();
335+
336+ // auto-exit if the window is closed
337+ if (render::engine->windowRequestsClose ()) {
338+ popContext ();
339+ }
340+ }
341+ } catch (...) {
342+ // Ensure cleanup happens even if an exception is thrown
343+ // NOTE: we don't really guarantee exception safety in general, it's likely that things are broken if an excpetion
344+ // was thrown. But this handles a few of the worst and most confusing cases.
345+ popContext ();
346+ cleanupContext ();
347+ throw ; // re-throw the exception after cleanup
327348 }
328349
329- // WARNING: code duplicated here and in screenshot.cpp
330- // Workaround overzealous ImGui assertion before destroying any inner context
331- // https://github.com/ocornut/imgui/pull/7175
332- newIO.BackendPlatformUserData = nullptr ;
333- newIO.BackendRendererUserData = nullptr ;
334- ImPlot::DestroyContext (newPlotContext);
335- ImGui::DestroyContext (newContext);
350+ cleanupContext ();
336351}
337352
338353
0 commit comments