Skip to content

Fix race condition crashes in Chart and Stack widgets#2944

Merged
exelban merged 1 commit intoexelban:masterfrom
andycjw:fix/concurrency-crashes
Feb 1, 2026
Merged

Fix race condition crashes in Chart and Stack widgets#2944
exelban merged 1 commit intoexelban:masterfrom
andycjw:fix/concurrency-crashes

Conversation

@andycjw
Copy link
Contributor

@andycjw andycjw commented Feb 1, 2026

Description:

This PR fixes multiple race conditions identified in StackWidget, NetworkChart, LineChart, and BarChart that were causing hard-to-reproduce crashes (SIGABRT and SIGTRAP) after extended runtimes (typically 1-3 days).

Issues

This issue always show up when 'Combined modules' is enabled.

The crashes stem from a classic Reader-Writer race condition between background module threads and the main UI thread.

SIGABRT in StackWidget (Memory Corruption):

Context: StackWidget maintains a values: [Stack_t] array. This array is passed as an UnsafeMutablePointer to its subview OrderTableView.

The Bug: The Sensors module (running on a background thread) updates the stack values via StackWidget.setValues. This method was mutating the values array directly on the background thread.

The Crash: If the background thread triggered a reallocation of the values array (e.g., during append or reassignment) while the Main Thread was simultaneously accessing it via the unsafe pointer in OrderTableView's drawing/delegate methods, the application would crash with a memory corruption error (swift_release_dealloc).

SIGTRAP in NetworkChart (Index Out of Bounds):

Context: NetworkChart maintains a points array for drawing the graph.

The Bug: The Net module (background thread) calls setValue(upload:download:), which was mutating (remove(at: 0) / append) the points array without any lock or thread affinity.

The Crash: The NetworkChart.draw(_:) method (Main Thread) iterates over this array to draw the paths. If the array is mutated by the background thread during this iteration, the bounds check fails (or the internal buffer is swapped out), triggering a SIGTRAP (assertion failure) for Index Out of Bounds.

Similar Patterns in LineChart and BarChart:
Identified similar unprotected mutations of self._value and other state variables (pressureLevel, colorZones) from background threads while they were being read/copied on the Main Thread for drawing.

The Fix
The fix ensures that all state mutations in these widgets are dispatched to the Main Thread, strictly serializing them with the drawing cycle.

StackWidget.swift: Wrapped setValues mutation logic in DispatchQueue.main.async. This ensures the array underlying the UnsafeMutablePointer is only touched by the Main Thread.

NetworkChart.swift
: Wrapped setValue array mutation in DispatchQueue.main.async.

LineChart.swift / BarChart.swift
: Wrapped setValue, setPressure, and configuration setters in
DispatchQueue.main.async.

Verification

Reproduction: Confirmed SIGABRT in Kit.StackWidget.setValues and SIGTRAP in Kit.NetworkChart.draw via custom signal handlers and stack trace logging during extended debugging sessions.

Stability Test: After applying the fixes, the application ran stable for 182+ hours (7.6 days) with zero crashes or issues, confirming the resolution.

Ensure data mutations from background readers are dispatched to the main thread to prevent conflicts with drawing logic (which runs on main thread). This resolves SIGTRAP and SIGABRT crashes observed during extended runtime.
@exelban exelban merged commit a69627f into exelban:master Feb 1, 2026
1 check passed
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.

2 participants