From 7d8202a63c00f343bef09fd9572a9cdc9f7f95ee Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Thu, 30 Sep 2021 07:33:43 -0400 Subject: [PATCH] Fix shm index update race There was a lingering issue where the fsp daemon would sync its shm array with the source data and we'd set the start/end indices to the same value. Under some races a reader would then read an empty `.array` which it wasn't expecting. This fixes that as well as tidies up the `ShmArray.push()` logic and adds a temporary check in `.array` for zero length if the array hasn't been written yet. We can now start removing read array length checks in consumer code and hopefully no more races will show up. --- piker/data/_sharedmem.py | 2 +- piker/ui/_chart.py | 33 ++++++++++++++++----------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/piker/data/_sharedmem.py b/piker/data/_sharedmem.py index 2169e262..8afa3214 100644 --- a/piker/data/_sharedmem.py +++ b/piker/data/_sharedmem.py @@ -220,7 +220,7 @@ class ShmArray: self, length: int = 1, ) -> np.ndarray: - return self.array[-length:] + return self.array[-length] def push( self, diff --git a/piker/ui/_chart.py b/piker/ui/_chart.py index 04f24d50..dc9387ea 100644 --- a/piker/ui/_chart.py +++ b/piker/ui/_chart.py @@ -936,11 +936,12 @@ class ChartPlotWidget(pg.PlotWidget): **kwargs, ) -> pg.GraphicsObject: - """Update the named internal graphics from ``array``. - - """ + '''Update the named internal graphics from ``array``. + ''' + assert len(array) data_key = array_key or graphics_name + if graphics_name not in self._overlays: self._arrays['ohlc'] = array else: @@ -948,21 +949,19 @@ class ChartPlotWidget(pg.PlotWidget): curve = self._graphics[graphics_name] - if len(array): - # TODO: we should instead implement a diff based - # "only update with new items" on the pg.PlotCurveItem - # one place to dig around this might be the `QBackingStore` - # https://doc.qt.io/qt-5/qbackingstore.html + # NOTE: back when we weren't implementing the curve graphics + # ourselves you'd have updates using this method: + # curve.setData(y=array[graphics_name], x=array['index'], **kwargs) - # NOTE: back when we weren't implementing the curve graphics - # ourselves you'd have updates using this method: - # curve.setData(y=array[graphics_name], x=array['index'], **kwargs) - - curve.update_from_array( - x=array['index'], - y=array[data_key], - **kwargs - ) + # NOTE: graphics **must** implement a diff based update + # operation where an internal ``FastUpdateCurve._xrange`` is + # used to determine if the underlying path needs to be + # pre/ap-pended. + curve.update_from_array( + x=array['index'], + y=array[data_key], + **kwargs + ) return curve