Previously the reaper thread would be unkillable if createPool was called in a masked context i.e.: pool <- mask_ $ createPool ... When pool gets garbage collected the KillThread exception can't be delivered to the reaper thread because it inherited the masked state of the calling thread. This could lead to a resource leak. Now we use: forkIOWithUnmask $ \unmask -> unmask ... which ensures asynchronous exception can always be delivered to the reaper thread.