Skip to content

Commit a69627f

Browse files
authored
fix: fixed race condition crashes in Chart and Stack widgets (#2944)
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.
1 parent 9f7b530 commit a69627f

File tree

4 files changed

+43
-37
lines changed

4 files changed

+43
-37
lines changed

Kit/Widgets/BarChart.swift

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -223,27 +223,33 @@ public class BarChart: WidgetWrapper {
223223
}
224224

225225
public func setValue(_ newValue: [[ColorValue]]) {
226-
let tolerance: CGFloat = 0.01
227-
let isDifferent = self._value.count != newValue.count || zip(self._value, newValue).contains { row1, row2 in
228-
row1.count != row2.count || zip(row1, row2).contains { val1, val2 in
229-
abs(val1.value - val2.value) > tolerance || val1.color != val2.color
226+
DispatchQueue.main.async(execute: {
227+
let tolerance: CGFloat = 0.01
228+
let isDifferent = self._value.count != newValue.count || zip(self._value, newValue).contains { row1, row2 in
229+
row1.count != row2.count || zip(row1, row2).contains { val1, val2 in
230+
abs(val1.value - val2.value) > tolerance || val1.color != val2.color
231+
}
230232
}
231-
}
232-
guard isDifferent else { return }
233-
self._value = newValue
234-
self.redraw()
233+
guard isDifferent else { return }
234+
self._value = newValue
235+
self.redraw()
236+
})
235237
}
236238

237239
public func setPressure(_ newPressureLevel: RAMPressure) {
238-
guard self._pressureLevel != newPressureLevel else { return }
239-
self._pressureLevel = newPressureLevel
240-
self.redraw()
240+
DispatchQueue.main.async(execute: {
241+
guard self._pressureLevel != newPressureLevel else { return }
242+
self._pressureLevel = newPressureLevel
243+
self.redraw()
244+
})
241245
}
242246

243247
public func setColorZones(_ newColorZones: colorZones) {
244-
guard self._colorZones != newColorZones else { return }
245-
self._colorZones = newColorZones
246-
self.redraw()
248+
DispatchQueue.main.async(execute: {
249+
guard self._colorZones != newColorZones else { return }
250+
self._colorZones = newColorZones
251+
self.redraw()
252+
})
247253
}
248254

249255
// MARK: - Settings

Kit/Widgets/LineChart.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,17 +249,17 @@ public class LineChart: WidgetWrapper {
249249
}
250250

251251
public func setValue(_ newValue: Double) {
252-
self._value = newValue
253252
DispatchQueue.main.async(execute: {
253+
self._value = newValue
254254
self.chart.addValue(newValue)
255255
self.display()
256256
})
257257
}
258258

259259
public func setPressure(_ newPressureLevel: RAMPressure) {
260-
guard self._pressureLevel != newPressureLevel else { return }
261-
self._pressureLevel = newPressureLevel
262260
DispatchQueue.main.async(execute: {
261+
guard self._pressureLevel != newPressureLevel else { return }
262+
self._pressureLevel = newPressureLevel
263263
self.display()
264264
})
265265
}

Kit/Widgets/NetworkChart.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,10 @@ public class NetworkChart: WidgetWrapper {
263263
}
264264

265265
public func setValue(upload: Double, download: Double) {
266-
self.points.remove(at: 0)
267-
self.points.append((upload, download))
268-
269266
DispatchQueue.main.async(execute: {
267+
self.points.remove(at: 0)
268+
self.points.append((upload, download))
269+
270270
if self.window?.isVisible ?? false {
271271
self.display()
272272
}

Kit/Widgets/Stack.swift

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -226,24 +226,24 @@ public class StackWidget: WidgetWrapper {
226226
}
227227

228228
public func setValues(_ values: [Stack_t]) {
229-
var tableNeedsToBeUpdated: Bool = false
230-
231-
values.forEach { (p: Stack_t) in
232-
if let idx = self.values.firstIndex(where: { $0.key == p.key }) {
233-
self.values[idx].value = p.value
234-
return
235-
}
236-
tableNeedsToBeUpdated = true
237-
self.values.append(p)
238-
}
239-
240-
let diff = self.values.filter({ v in values.contains(where: { $0.key == v.key }) })
241-
if diff.count != self.values.count {
242-
tableNeedsToBeUpdated = true
243-
}
244-
self.values = diff.sorted(by: { $0.index < $1.index })
245-
246229
DispatchQueue.main.async(execute: {
230+
var tableNeedsToBeUpdated: Bool = false
231+
232+
values.forEach { (p: Stack_t) in
233+
if let idx = self.values.firstIndex(where: { $0.key == p.key }) {
234+
self.values[idx].value = p.value
235+
return
236+
}
237+
tableNeedsToBeUpdated = true
238+
self.values.append(p)
239+
}
240+
241+
let diff = self.values.filter({ v in values.contains(where: { $0.key == v.key }) })
242+
if diff.count != self.values.count {
243+
tableNeedsToBeUpdated = true
244+
}
245+
self.values = diff.sorted(by: { $0.index < $1.index })
246+
247247
if tableNeedsToBeUpdated {
248248
self.orderTableView.update()
249249
}

0 commit comments

Comments
 (0)