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)

Open
#2,662 1 comment 0 reactions 0 assignees View on GitHub
state: pending type: bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.