Dear PyGui version:
2.3.1 (also reproduced on 2.2.0 and 2.3.0; the call is still missing in current master source; last good release: 2.1.1)
Python version:
3.13.5
Operating system:
Windows 11
My issue/question:
On Windows, destroy_context() returns but does not destroy the viewport's OS window. The window is left orphaned with nothing pumping its message queue, so Windows marks it "Not Responding." In a normal script this is invisible — the process exits and the OS reaps the window — but in any long-lived process (python -i, running from a REPL, an embedded interpreter) the frozen window lingers until the interpreter exits. This is not a hang: the interpreter stays fully responsive the whole time. 2.1.1 destroyed the window correctly.
Root cause (from source)
mvCleanupViewport() — the only function that calls ::DestroyWindow() — is unchanged between 2.1.1 and 2.3.1, but the destroy_context() rewrite that landed in 2.2.0 (PR #2580) stopped calling it:
// v2.1.1 — src/dearpygui_commands.h, destroy_context():
if (GContext->viewport != nullptr)
mvCleanupViewport(*GContext->viewport); // ImGui_ImplWin32_Shutdown(); ::DestroyWindow(); ::UnregisterClass()
...
ImGui::DestroyContext();
// v2.2.0 .. master — destroy_context() rewritten in #2580; mvCleanupViewport is never called:
ImGui::DestroyContext();
...
if (GContext->viewport)
delete GContext->viewport; // frees the C++ struct only — mvViewport has no destructor; the OS window survives
A tree-wide grep confirms it: in v2.1.1 mvCleanupViewport has exactly one caller (destroy_context, dearpygui_commands.h:2671); in v2.2.0, v2.3.1, and current master it is defined for win32/linux/apple and never called — dead code.
This looks unintentional rather than a design change: #2580 is a callback-refcount fix whose rewrite of destroy_context re-sequenced callback-thread shutdown, and nothing in the PR mentions the viewport window. Notably, the same PR edits the inside of mvCleanupViewport (mvViewport_linux.cpp: GContext->started = false → StopRendering()) while removing its only caller — the function was still being maintained as live code.
Steps to reproduce:
pip install dearpygui==2.3.1 (same result on 2.2.0 / 2.3.0)
- Start an interactive interpreter:
python -i
- Paste the minimal example below.
- After
destroy_context() returns, the "REPRO" window is still on screen, frozen ("Not Responding"); the interpreter prompt is fully responsive (1+1 works).
- Repeat on
dearpygui==2.1.1: the window disappears at destroy_context().
Expected behavior:
destroy_context() destroys the viewport's OS window and unregisters its window class (as in 2.1.1 and earlier), and ImGui_ImplWin32_Shutdown() runs before ImGui::DestroyContext(). No frozen window should remain when the process keeps running.
Screenshots:
N/A
Standalone, minimal, complete and verifiable example:
# run inside `python -i` (any long-lived process) on Windows, dearpygui 2.2.0-2.3.1
import dearpygui.dearpygui as dpg
dpg.create_context()
with dpg.window(label="main", tag="main"):
dpg.add_button(label="OK")
dpg.create_viewport(title="REPRO", width=320, height=200)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.set_primary_window("main", True)
for _ in range(30):
dpg.render_dearpygui_frame()
dpg.stop_dearpygui()
dpg.destroy_context()
# 2.1.1: the REPRO window is gone.
# 2.2.0+: the REPRO window remains on screen, frozen ("Not Responding"),
# while the interpreter stays fully responsive.
Dear PyGui version:
2.3.1 (also reproduced on 2.2.0 and 2.3.0; the call is still missing in current master source; last good release: 2.1.1)
Python version:
3.13.5
Operating system:
Windows 11
My issue/question:
On Windows,
destroy_context()returns but does not destroy the viewport's OS window. The window is left orphaned with nothing pumping its message queue, so Windows marks it "Not Responding." In a normal script this is invisible — the process exits and the OS reaps the window — but in any long-lived process (python -i, running from a REPL, an embedded interpreter) the frozen window lingers until the interpreter exits. This is not a hang: the interpreter stays fully responsive the whole time. 2.1.1 destroyed the window correctly.Root cause (from source)
mvCleanupViewport()— the only function that calls::DestroyWindow()— is unchanged between 2.1.1 and 2.3.1, but thedestroy_context()rewrite that landed in 2.2.0 (PR #2580) stopped calling it:A tree-wide grep confirms it: in v2.1.1
mvCleanupViewporthas exactly one caller (destroy_context,dearpygui_commands.h:2671); in v2.2.0, v2.3.1, and current master it is defined for win32/linux/apple and never called — dead code.This looks unintentional rather than a design change: #2580 is a callback-refcount fix whose rewrite of
destroy_contextre-sequenced callback-thread shutdown, and nothing in the PR mentions the viewport window. Notably, the same PR edits the inside ofmvCleanupViewport(mvViewport_linux.cpp:GContext->started = false→StopRendering()) while removing its only caller — the function was still being maintained as live code.Steps to reproduce:
pip install dearpygui==2.3.1(same result on 2.2.0 / 2.3.0)python -idestroy_context()returns, the "REPRO" window is still on screen, frozen ("Not Responding"); the interpreter prompt is fully responsive (1+1works).dearpygui==2.1.1: the window disappears atdestroy_context().Expected behavior:
destroy_context()destroys the viewport's OS window and unregisters its window class (as in 2.1.1 and earlier), andImGui_ImplWin32_Shutdown()runs beforeImGui::DestroyContext(). No frozen window should remain when the process keeps running.Screenshots:
N/A
Standalone, minimal, complete and verifiable example: