on master help sign in
Fix ahead style nil stream merging live lock
49542d2Harendra Kumar
Changelog.md+8
@@ -1,3 +1,11 @@
1+## Unreleased
2+
3+### Bug Fixes
4+
5+* Fixed a livelock in ahead style streams. The problem manifests sometimes when
6+ multiple streams are merged together in ahead style and one of them is a nil
7+ stream.
8+
1## 0.5.1
9## 0.5.1
2
10
3* Performance improvements, especially space consumption, for concurrent
11* Performance improvements, especially space consumption, for concurrent
src/Streamly/SVar.hs+2−1
@@ -189,7 +189,8 @@ data ChildEvent a =
189
189
190-- | Sorting out-of-turn outputs in a heap for Ahead style streams
190-- | Sorting out-of-turn outputs in a heap for Ahead style streams
191data AheadHeapEntry (t :: (* -> *) -> * -> *) m a =
191data AheadHeapEntry (t :: (* -> *) -> * -> *) m a =
192+ AheadEntryNull
192− AheadEntryPure a
193+ | AheadEntryPure a
193 | AheadEntryStream (t m a)
194 | AheadEntryStream (t m a)
194
195
195------------------------------------------------------------------------------
196------------------------------------------------------------------------------
src/Streamly/Streams/Ahead.hs+7−1
@@ -230,6 +230,7 @@ processHeap q heap st sv winfo entry sno stopping = loopHeap sno entry
230
230
231 loopHeap seqNo ent =
231 loopHeap seqNo ent =
232 case ent of
232 case ent of
233+ AheadEntryNull -> nextHeap seqNo
233 AheadEntryPure a -> do
234 AheadEntryPure a -> do
234 -- Use 'send' directly so that we do not account this in worker
235 -- Use 'send' directly so that we do not account this in worker
235 -- latency as this will not be the real latency.
236 -- latency as this will not be the real latency.
@@ -338,7 +339,12 @@ processWithoutToken q heap st sv winfo m sno = do
338 -- we have already decremented the yield limit for m
339 -- we have already decremented the yield limit for m
339 let stop = do
340 let stop = do
340 liftIO (incrementYieldLimit sv)
341 liftIO (incrementYieldLimit sv)
341− workLoopAhead q heap st sv winfo
342+ -- If the stream stops without yielding anything, and we do not put
343+ -- anything on heap, but if heap was waiting for this seq number
344+ -- then it will keep waiting forever, because we are never going to
345+ -- put it on heap. So we have to put a null entry on heap even when
346+ -- we stop.
347+ toHeap sno AheadEntryNull
342
348
343 unStream m st stop (singleToHeap sno) (yieldToHeap sno)
349 unStream m st stop (singleToHeap sno) (yieldToHeap sno)
344
350