hoffstadt / hoffstadt/DearPyGui
destroy_context() no longer destroys the viewport OS window — mvCleanupViewport() lost its only caller in #2580 (regression: 2.2.0+; last good: 2.1.1)
- Dominant language
- C++
- Stars
- 15.6k
- Forks
- 783
- PR merge metrics
- No merged PRs in 30d
Description
### 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**:
```cpp
// 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:
1. `pip install dearpygui==2.3.1` (same result on 2.2.0 / 2.3.0)
2. Start an interactive interpreter: `python -i`
3. Paste the minimal example below.
4. After `destroy_context()` returns, the "REPRO" window is still on screen, frozen ("Not Responding"); the interpreter prompt is fully responsive (`1+1` works).
5. 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:
```python
# 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.
```
Contributor guide
Research direction
Start in src/dearpygui_commands.h at destroy_context() and trace the existing mvCleanupViewport() implementations; the issue also points to mvViewport_linux.cpp. Compare the 2.1.1 and current shutdown paths, then run the provided python -i reproduction on Windows. Done means destroy_context() removes the viewport OS window and unregisters its class before ImGui context teardown, without leaving a frozen window.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, python
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100