From 889ed903d7ff4fa20cef48b8e73d03c2a947c7fb Mon Sep 17 00:00:00 2001 From: Nathan Faubion Date: Sat, 18 Nov 2017 15:27:04 -0800 Subject: [PATCH] Fix ParAff cancellation Fixes #130 --- src/Control/Monad/Aff.js | 18 +++++++++++++----- test/Test/Main.purs | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/Control/Monad/Aff.js b/src/Control/Monad/Aff.js index c4b1945..51ac249 100644 --- a/src/Control/Monad/Aff.js +++ b/src/Control/Monad/Aff.js @@ -536,7 +536,9 @@ var Aff = function () { joins[jid] = join; return function() { - delete joins[jid]; + if (joins !== null) { + delete joins[jid]; + } }; }; } @@ -937,14 +939,20 @@ var Aff = function () { } // Cancels the entire tree. If there are already subtrees being canceled, - // we need to first cancel those joins. This is important so that errors - // don't accidentally get swallowed by irrelevant join callbacks. + // we need to first cancel those joins. We will then add fresh joins for + // all pending branches including those that were in the process of being + // canceled. function cancel(error, cb) { interrupt = util.left(error); - + var innerKills; for (var kid in kills) { if (kills.hasOwnProperty(kid)) { - kills[kid](); + innerKills = kills[kid]; + for (kid in innerKills) { + if (innerKills.hasOwnProperty(kid)) { + innerKills[kid](); + } + } } } diff --git a/test/Test/Main.purs b/test/Test/Main.purs index 705c5a7..2b1771b 100644 --- a/test/Test/Main.purs +++ b/test/Test/Main.purs @@ -513,6 +513,25 @@ test_kill_parallel_alt = assert "kill/parallel/alt" do _ ← try $ joinFiber f2 eq "killedfookilledbardone" <$> readRef ref +test_kill_parallel_alt_finalizer ∷ ∀ eff. TestAff eff Unit +test_kill_parallel_alt_finalizer = assert "kill/parallel/alt/finalizer" do + ref ← newRef "" + f1 ← forkAff $ sequential $ + parallel (delay (Milliseconds 10.0)) <|> parallel do + bracket + (pure unit) + (\_ → do + delay (Milliseconds 10.0) + modifyRef ref (_ <> "killed")) + (\_ → delay (Milliseconds 20.0)) + f2 ← forkAff do + delay (Milliseconds 15.0) + killFiber (error "Nope") f1 + modifyRef ref (_ <> "done") + _ ← try $ joinFiber f1 + _ ← try $ joinFiber f2 + eq "killeddone" <$> readRef ref + test_fiber_map ∷ ∀ eff. TestAff eff Unit test_fiber_map = assert "fiber/map" do ref ← newRef 0 @@ -628,6 +647,7 @@ main = do test_parallel_alt_sync test_parallel_mixed test_kill_parallel_alt + test_kill_parallel_alt_finalizer test_avar_order test_efffn test_fiber_map