Skip to content

Bugfix: Cancel Scheduled Dashboard Updates#105

Open
danielegelhoff13 wants to merge 9 commits intodevelopfrom
bugfix/cancel-scheduled-updates
Open

Bugfix: Cancel Scheduled Dashboard Updates#105
danielegelhoff13 wants to merge 9 commits intodevelopfrom
bugfix/cancel-scheduled-updates

Conversation

@danielegelhoff13
Copy link
Copy Markdown

@danielegelhoff13 danielegelhoff13 commented Apr 14, 2026

Description

This PR is targeted bugfix to remove printed console errors of the form:

invalid command name "1912854347264update_status"
    while executing
"1912854347264update_status"
    ("after" script)

These errors come from scheduled Tkinter Dashboard updates that are not cancelled when the app is quit, and so try to modify the Dashboard which no longer exists.

Additionally, this PR fixes a bug where the Dashboard's cleanup path was not invoked by just clicking the 'X' in the top right corner of the screen. Now, both Ctrl+Q and clicking the 'X' will trigger the correct Dashboard cleanup and shutdown path.

NOTE: This PR is a subset of the changes made in PR 83: Graceful Exit. The goal is to pare down the changes in that large PR into smaller ones for ease of testing and clarity.

Summary of the Fix

Each subsystem file that uses Tkinter's after() function to schedule a Dashboard update in the future has been modified:

  • Cathode Heating
  • Interlocks
  • Oil System
  • Process Monitor

In each subsystem, a cancel_updates() function has been defined and is called by cleanup() in dashboard.py. Additionally in dashboard.py, scheduled COM port checks are canceled.

Tests Run

A full hardware test was run with all subsystems on 4/15/2026. The result was a success, and is documented here:

https://docs.google.com/document/d/1l9kT7njyEyAE3uNlWtzscGo2fp0MtTuWE9y5YJYrxlM/edit?tab=t.0 (on page 3)

@danielegelhoff13 danielegelhoff13 added Dashboard bug Something isn't working labels Apr 14, 2026
@danielegelhoff13
Copy link
Copy Markdown
Author

After running a hardware test with all subsystems on, I will open this PR for review/merge.

Comment thread main.py
return "break"

"""Esnure that quit_app is called when the window is closed, not just when Ctrl+Q is pressed."""
root.protocol("WM_DELETE_WINDOW", quit_app)
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the modification of quit behavior. When the window is closed, the same pop-up will appear saying "Do you want to quit?", and dashboard.py's cleanup() function will be invoked.

@danielegelhoff13
Copy link
Copy Markdown
Author

Testing finished, this PR is ready for review and merge.

@danielegelhoff13 danielegelhoff13 marked this pull request as ready for review April 15, 2026 20:27
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 864c11c10c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread subsystem/interlocks/interlocks.py Outdated
# Schedule next update
if self.driver:
self.parent.after(self.update_interval, self.update_data)
self.after_id = self.parent.after(self.update_interval, self.update_data)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Cancel all pending interlock timers on shutdown

This change records only one timer handle in self.after_id, but InterlocksSubsystem can still schedule other after() callbacks outside this tracked assignment (e.g., startup scheduling and the status is None retry path). In those cases, cancel_updates() will cancel only the last stored handle, leaving an untracked callback that can run after Tk teardown and continue producing shutdown-time after/invalid-command errors. Route all scheduling through a single tracked handle (or track a set of handles) so cleanup can reliably cancel every pending callback.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was issue; callbacks were being scheduled in 2 places in interlocks.py, but both were scheduling callbacks to the same update_data() function. So I defined _schedule_update() that only allows one callback to be scheduled at a time, preserving behavior and removing the possibility that 2 would exist at once, and not be cleanly cancelled.

Commit 9328a1e fixed this issue.

…nction, only allowing one callback of the update_data function to be scheduled.
@danielegelhoff13
Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@MathomJohnson
Copy link
Copy Markdown
Member

The cancel_updates() method in interlocks.py sets after_id=None after cancelling. In cathode_heating.py and oil_system.py you don't set after_id=None in the cancel_updates() method. This isn't a bug because this is only called on exit so it shouldn't matter. But, for the sake of consistency you might consider looking into this.

… after_id to None. Not required as cancel_updates() is only called once, but more rigorous.
@danielegelhoff13
Copy link
Copy Markdown
Author

danielegelhoff13 commented Apr 21, 2026

The cancel_updates() method in interlocks.py sets after_id=None after cancelling. In cathode_heating.py and oil_system.py you don't set after_id=None in the cancel_updates() method. This isn't a bug because this is only called on exit so it shouldn't matter. But, for the sake of consistency you might consider looking into this.

Thanks Mathom, good catch. I fixed this in commit 51af636. The way that interlocks.py set after_id = None after the cancellation is slightly more rigorous and correct, albeit not needed as cancel_updates() is only called once per subsystem, so I changed the other subsystem's cancel_updates() functions to do the same.

I also added a note to utils.py detailing why logging of the cancellation is not done there (because the MachineStatus class does not have a logger object and it is not needed).

@bwalkerMIR
Copy link
Copy Markdown
Collaborator

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copilot AI pushed a commit that referenced this pull request Apr 28, 2026
Co-authored-by: sbasu107 <40325803+sbasu107@users.noreply.github.com>
Copilot AI pushed a commit that referenced this pull request Apr 28, 2026
Resolved conflicts in:
- main.py: kept both 'KnobBox' and 'BeamPulse' in SUBSYSTEMS list
- dashboard.py: kept ports_after_id from #105 + toggle images and BeamPulse subsystem init from BCON-lite
- subsystem/cathode_heating/cathode_heating.py: kept HEAD's LUT-based logic (from #90) plus BCON-lite's turn_off_all_beams and set_target_current additions

Co-authored-by: sbasu107 <40325803+sbasu107@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working Dashboard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants