bug : chartread does not terminate when closing ICCery in stage 3 without hitting cancel #147

Closed
opened 2026-08-30 11:41:04 +01:00 by gronod · 0 comments
Owner

Description

When the user is in Stage 3 (Interactive Measurement) with an active chartread process and closes the ICCery window (or quits the app) without pressing Cancel, the chartread subprocess is left running.

The OS process continues to hold the instrument, keep USB/serial resources open, and may still be waiting on stdin prompts. Subsequent launches of ICCery (or other tools) can then fail to open the spectrophotometer until the orphaned process is killed manually.

Cancel works correctly because the UI explicitly calls kill_process. Window/app close does not.

Steps to Reproduce

  1. Launch ICCery and progress to Stage 3.
  2. Start a measurement (chartread is spawned; Cancel button becomes visible).
  3. Do not press Cancel.
  4. Close the ICCery window (title-bar close, Cmd/Ctrl+Q, or OS quit).
  5. Observe the system process list (Activity Monitor / Task Manager / ps).

Expected Behaviour

  • On window close or app exit, any managed Argyll subprocesses (especially the interactive chartread_* process) are terminated.
  • Instrument handles are released cleanly.
  • No orphaned chartread (or other sidecar) processes remain.

Actual Behaviour

  • chartread continues running after ICCery has exited.
  • The process only disappears if the user previously hit Cancel (which calls invoke("kill_process", { id })) or if it is killed externally.

Technical Notes

  • ProcessManager already supports cooperative kill via a oneshot channel + child.start_kill() (src-tauri/src/process_manager.rskill()).
  • Frontend Cancel path correctly uses this (src/js/chartread.jsbtnCancel click handler).
  • There is currently no Tauri RunEvent::Exit / WindowEvent::CloseRequested (or equivalent) handler that walks active process IDs and calls kill / kill_all on shutdown.
  • Because chartread is interactive and holds the instrument, an orphan is particularly painful compared to short-lived tools like targen or colprof.

Suggested Fix

  1. Add a shutdown path (e.g. on RunEvent::Exit or window close) that terminates every process still registered in ProcessManager.
  2. Optionally also close stdin before signalling kill, matching the existing kill() behaviour.
  3. Consider a small kill_all() helper on ProcessManager for clarity.
  4. Verify on Windows, Linux, and macOS that the child does not survive the parent.

Acceptance Criteria

  • Closing ICCery during an active Stage 3 measurement leaves no chartread (or other Argyll) process running.
  • Cancel button behaviour remains unchanged and correct.
  • Instrument is released and can be re-opened by a new ICCery session without manual intervention.
  • Same cleanup applies if the user quits from any stage while a subprocess is alive (not only Stage 3).

Environment

  • Observed with interactive chartread in Stage 3.
  • Affects all platforms; severity highest where the instrument lock persists (USB spectrophotometers).

Dependencies & Ordering

  • Kind: Bug
  • Priority: High (leaves hardware locked / confuses subsequent runs)
  • Milestone: (assign as appropriate — production readiness / v0.5.x)
### Description When the user is in **Stage 3 (Interactive Measurement)** with an active `chartread` process and closes the ICCery window (or quits the app) **without** pressing Cancel, the `chartread` subprocess is left running. The OS process continues to hold the instrument, keep USB/serial resources open, and may still be waiting on stdin prompts. Subsequent launches of ICCery (or other tools) can then fail to open the spectrophotometer until the orphaned process is killed manually. Cancel works correctly because the UI explicitly calls `kill_process`. Window/app close does not. ### Steps to Reproduce 1. Launch ICCery and progress to Stage 3. 2. Start a measurement (`chartread` is spawned; Cancel button becomes visible). 3. Do **not** press Cancel. 4. Close the ICCery window (title-bar close, Cmd/Ctrl+Q, or OS quit). 5. Observe the system process list (Activity Monitor / Task Manager / `ps`). ### Expected Behaviour - On window close or app exit, any managed Argyll subprocesses (especially the interactive `chartread_*` process) are terminated. - Instrument handles are released cleanly. - No orphaned `chartread` (or other sidecar) processes remain. ### Actual Behaviour - `chartread` continues running after ICCery has exited. - The process only disappears if the user previously hit Cancel (which calls `invoke("kill_process", { id })`) or if it is killed externally. ### Technical Notes - `ProcessManager` already supports cooperative kill via a oneshot channel + `child.start_kill()` (`src-tauri/src/process_manager.rs` → `kill()`). - Frontend Cancel path correctly uses this (`src/js/chartread.js` → `btnCancel` click handler). - There is currently **no** Tauri `RunEvent::Exit` / `WindowEvent::CloseRequested` (or equivalent) handler that walks active process IDs and calls `kill` / `kill_all` on shutdown. - Because `chartread` is interactive and holds the instrument, an orphan is particularly painful compared to short-lived tools like `targen` or `colprof`. ### Suggested Fix 1. Add a shutdown path (e.g. on `RunEvent::Exit` or window close) that terminates every process still registered in `ProcessManager`. 2. Optionally also close stdin before signalling kill, matching the existing `kill()` behaviour. 3. Consider a small `kill_all()` helper on `ProcessManager` for clarity. 4. Verify on Windows, Linux, and macOS that the child does not survive the parent. ### Acceptance Criteria - [ ] Closing ICCery during an active Stage 3 measurement leaves no `chartread` (or other Argyll) process running. - [ ] Cancel button behaviour remains unchanged and correct. - [ ] Instrument is released and can be re-opened by a new ICCery session without manual intervention. - [ ] Same cleanup applies if the user quits from any stage while a subprocess is alive (not only Stage 3). ### Environment - Observed with interactive `chartread` in Stage 3. - Affects all platforms; severity highest where the instrument lock persists (USB spectrophotometers). ### Dependencies & Ordering - **Kind**: Bug - **Priority**: High (leaves hardware locked / confuses subsequent runs) - **Milestone**: (assign as appropriate — production readiness / v0.5.x)
gronod added the Kind/Bug
Reviewed
Confirmed
1
Priority
Medium
3
labels 2026-08-30 11:41:04 +01:00
gronod added
Priority
High
2
Reviewed
Duplicate
2
and removed
Priority
Medium
3
Reviewed
Confirmed
1
labels 2026-08-30 12:04:46 +01:00
gronod added
Reviewed
Confirmed
1
and removed
Reviewed
Duplicate
2
labels 2026-08-30 15:10:57 +01:00
gronod added this to the Milestone 10: Production Ready Features (v0.6.0) milestone 2026-08-30 15:15:03 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: gronod/ICCery#147