jwiegley / async-pool

Other
21 stars 13 forks source link

Cancelling an async immediately after its creation causes exception in `runTaskGroup` #31

Open lsrcz opened 5 months ago

lsrcz commented 5 months ago

The runTaskGroup function can crash with a "Match Exception" error when an async task is created and cancelled before it is scheduled to run. This issue can lead to unexpected behavior, such as the subsequent async tasks in the task group not being executed.

Consider the following example:

import Control.Concurrent.Async as Async
import Control.Concurrent.Async.Pool as Pool
import Control.Exception

do
  pool <- Pool.createPool
  group <- Pool.createTaskGroup pool 2
  mainThread <- Async.async $ runTaskGroup group `catch` (\(e :: SomeException) -> print e)
  Pool.async group (print "x") >>= Pool.cancel
  Pool.async group (print "y")

In this code, the first async task is created and immediate cancelled before it has a chance to be scheduled. Then y will never be printed. The error message looks like this:

Match Exception, Node: 0
CallStack (from HasCallStack):
  error, called at ./Data/Graph/Inductive/Graph.hs:385:26 in fgl-5.8.2.0-AeC32udtCeIHgQIC5kCLt:Data.Graph.Inductive.Graph

The following code consistently reproduce this issue:

do
  pool <- Pool.createPool
  group <- Pool.createTaskGroup pool 2
  x <- Pool.async group $ print "x"
  Pool.cancel x
  Pool.runTaskGroup group