Skip to content

Fix crash and stalled Windows shutdown when MyFrame::OnClose runs twice - #1475

Draft
riggsbrown wants to merge 1 commit into
OpenPHDGuiding:masterfrom
riggsbrown:fix/onclose-reentry
Draft

riggsbrown wants to merge 1 commit into
OpenPHDGuiding:masterfrom
riggsbrown:fix/onclose-reentry

Conversation

@riggsbrown

Copy link
Copy Markdown

Fixes #1474

MyFrame::OnClose deletes the help controller and sets help to null. A second call then
crashes at help->GetFrame(). On Windows that second call is routine:

  • Logoff/restart: wx 3.0.5 forwards every WM_QUERYENDSESSION to wxApp::OnQueryEndSession,
    which calls Close() on the top window. Windows sends the message to each top-level window, and
    PHD2 has several (main frame, hidden wxWindowNR, Advanced Settings, Connect Equipment). The
    crash leaves phd2.exe running and Windows abandons the restart. On an unattended observatory
    that leaves the PC sitting at the lock screen with nothing running.
  • Manual exit: clicking X again while the frame is still on screen (wx doesn't hide the last
    visible TLW in Destroy()).

On one rig this is 34 crashes at phd2.exe+0x1D3EB3 in 2.6.14 since June, and 5 abandoned Windows
restarts. Details, disassembly and logs are in the issue.

Change

  • Add m_closed, set once OnClose passes the veto check. Later calls log
    MyFrame::OnClose already closed and return without vetoing, so the close or end-session goes
    ahead, and Destroy() from the first call is already pending.
  • Null-check help before using it.

The veto path is unchanged: if the user cancels the "exit while capturing" prompt, m_closed stays
false and a later close runs the full shutdown.

Testing

  • Builds on Windows (this repo's only CI workflow is the clang-format check)
  • clang-format check (CI)
  • repro_double_close.py --send against PHD2 + simulator: one OnClose proceeding, then
    OnClose already closed for each later message, and phd2.exe exits with no crash
  • Windows restart with PHD2 running and connected: restart completes
  • Normal File > Exit and window X: unchanged

I could not build this locally (no MSVC toolchain on the machine where it was found). The boxes
above are the plan, not results.

🤖 Generated with Claude Code

On Windows, wxApp::OnQueryEndSession calls Close() on the top window for
every WM_QUERYENDSESSION, and Windows sends that message to each of the
application's top-level windows (the main frame, the Advanced Settings and
Connect Equipment dialogs, ...). MyFrame::OnClose therefore runs more than
once during a logoff or restart. The second call dereferences the help
controller that the first call deleted and set to null
(help->GetFrame()), an access violation at a fixed offset in phd2.exe.

Observed on 2.6.14 (32-bit) under Windows 11: the crash during the
restart's query phase leaves phd2.exe running, Windows abandons the restart
("failed to terminate the currently logged on user's processes") and the
user is returned to the lock screen with the rest of their session already
closed. For unattended remote observatories that is a night lost.

Make OnClose idempotent: remember that the shutdown has run and return
early on later calls, and null-check help before using it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crash (null help) when MyFrame::OnClose runs twice, blocking Windows restarts on unattended rigs

1 participant