Skip to content

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) #2662

Description

@bca195678

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 = falseStopRendering()) 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:

# 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.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions