diff --git a/hspec-core.cabal b/hspec-core.cabal
--- a/hspec-core.cabal
+++ b/hspec-core.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:             hspec-core
-version:          2.8.2
+version:          2.8.3
 license:          MIT
 license-file:     LICENSE
 copyright:        (c) 2011-2021 Simon Hengel,
@@ -35,7 +35,7 @@
   build-depends:
       HUnit ==1.6.*
     , QuickCheck >=2.13.1
-    , ansi-terminal >=0.5
+    , ansi-terminal >=0.6.2
     , array
     , base >=4.5.0.0 && <5
     , call-stack
@@ -97,7 +97,7 @@
   build-depends:
       HUnit ==1.6.*
     , QuickCheck >=2.14
-    , ansi-terminal >=0.5
+    , ansi-terminal >=0.6.2
     , array
     , base >=4.5.0.0 && <5
     , call-stack
@@ -160,6 +160,7 @@
       Test.Hspec.Core.Example.LocationSpec
       Test.Hspec.Core.ExampleSpec
       Test.Hspec.Core.FailureReportSpec
+      Test.Hspec.Core.FormatSpec
       Test.Hspec.Core.Formatters.DiffSpec
       Test.Hspec.Core.Formatters.InternalSpec
       Test.Hspec.Core.Formatters.V1Spec
diff --git a/src/Test/Hspec/Core/Format.hs b/src/Test/Hspec/Core/Format.hs
--- a/src/Test/Hspec/Core/Format.hs
+++ b/src/Test/Hspec/Core/Format.hs
@@ -19,8 +19,10 @@
 import           Prelude ()
 import           Test.Hspec.Core.Compat
 
+import           Control.Exception
 import           Control.Concurrent
 import           Control.Concurrent.Async (async)
+import qualified Control.Concurrent.Async as Async
 import           Control.Monad.IO.Class
 
 import           Test.Hspec.Core.Spec (Progress, Location(..))
@@ -63,6 +65,8 @@
 , formatConfigItemCount :: Int
 } deriving (Eq, Show)
 
+data Signal = Ok | NotOk SomeException
+
 monadic :: MonadIO m => (m () -> IO ()) -> (Event -> m ()) -> IO Format
 monadic run format = do
   mvar <- newEmptyMVar
@@ -75,10 +79,10 @@
     takeEvent :: MonadIO m => m Event
     takeEvent = liftIO $ takeMVar mvar
 
-    signal :: MonadIO m => m ()
-    signal = liftIO $ putMVar done ()
+    signal :: MonadIO m => Signal -> m ()
+    signal = liftIO . putMVar done
 
-    wait :: IO ()
+    wait :: IO Signal
     wait = takeMVar done
 
     go = do
@@ -87,13 +91,21 @@
       case event of
         Done {} -> return ()
         _ -> do
-          signal
+          signal Ok
           go
 
-  _ <- async $ do
-    run go
-    signal
+  t <- async $ do
+    (run go >> signal Ok) `catch` (signal . NotOk)
 
   return $ \ event -> do
-    putEvent event
-    wait
+    running <- Async.poll t
+    case running of
+      Just _ -> return ()
+      Nothing -> do
+        putEvent event
+        r <- wait
+        case r of
+          Ok -> return ()
+          NotOk err -> do
+            Async.wait t
+            throwIO err
diff --git a/src/Test/Hspec/Core/Runner.hs b/src/Test/Hspec/Core/Runner.hs
--- a/src/Test/Hspec/Core/Runner.hs
+++ b/src/Test/Hspec/Core/Runner.hs
@@ -45,6 +45,7 @@
 import           System.Random
 import           Control.Monad.ST
 import           Data.STRef
+import           System.Console.ANSI (hSupportsANSI)
 
 import           System.Console.ANSI (hHideCursor, hShowCursor)
 import qualified Test.QuickCheck as QC
@@ -211,7 +212,7 @@
     Nothing -> getDefaultConcurrentJobs
     Just n -> return n
 
-  useColor <- colorOutputSupported (configColorMode config) (hIsTerminalDevice stdout)
+  useColor <- colorOutputSupported (configColorMode config) (hSupportsANSI stdout)
 
   results <- withHiddenCursor useColor stdout $ do
     let
@@ -286,26 +287,12 @@
 
 colorOutputSupported :: ColorMode -> IO Bool -> IO Bool
 colorOutputSupported mode isTerminalDevice = case mode of
-  ColorAuto  -> (not <$> noColor ||^ isDumb) &&^ isTerminalDevice
+  ColorAuto  -> (&&) <$> (not <$> noColor) <*> isTerminalDevice
   ColorNever -> return False
   ColorAlways -> return True
 
 noColor :: IO Bool
 noColor = lookupEnv "NO_COLOR" <&> (/= Nothing)
-
-isDumb :: IO Bool
-isDumb = lookupEnv "TERM" <&> (== Just "dumb")
-
-(||^) :: IO Bool -> IO Bool -> IO Bool
-(||^) a b = ifM a (pure True) b
-
-(&&^) :: IO Bool -> IO Bool -> IO Bool
-(&&^) a b = ifM a b (pure False)
-
-ifM :: IO Bool -> IO a -> IO a -> IO a
-ifM action true false = do
-  bool <- action
-  if bool then true else false
 
 rerunAll :: Config -> Maybe FailureReport -> Summary -> Bool
 rerunAll _ Nothing _ = False
diff --git a/test/Test/Hspec/Core/FormatSpec.hs b/test/Test/Hspec/Core/FormatSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Hspec/Core/FormatSpec.hs
@@ -0,0 +1,21 @@
+module Test.Hspec.Core.FormatSpec (spec) where
+
+import           Prelude ()
+import           Helper
+
+import           Control.Exception
+
+import           Test.Hspec.Core.Format
+
+spec :: Spec
+spec = do
+  describe "monadic" $ do
+    context "on exception" $ do
+      it "propagates" $ do
+        format <- monadic id (\ _ -> throwIO DivideByZero)
+        format (Done []) `shouldThrow` (== DivideByZero)
+
+      it "does not hang" $ do
+        format <- monadic id (\ _ -> throwIO DivideByZero)
+        format (Done []) `shouldThrow` (== DivideByZero)
+        format (Done [])
diff --git a/test/Test/Hspec/Core/RunnerSpec.hs b/test/Test/Hspec/Core/RunnerSpec.hs
--- a/test/Test/Hspec/Core/RunnerSpec.hs
+++ b/test/Test/Hspec/Core/RunnerSpec.hs
@@ -586,11 +586,6 @@
         withEnvironment [] $ do
           H.colorOutputSupported H.ColorAuto isTerminalDevice `shouldReturn` True
 
-      context "when TERM=dumb" $ do
-        it "returns False" $ do
-          withEnvironment [("TERM", "dumb")] $ do
-            H.colorOutputSupported H.ColorAuto isTerminalDevice `shouldReturn` False
-
       context "when NO_COLOR is set" $ do
         it "returns False" $ do
           withEnvironment [("NO_COLOR", "yes")] $ do
diff --git a/version.yaml b/version.yaml
--- a/version.yaml
+++ b/version.yaml
@@ -1,1 +1,1 @@
-&version 2.8.2
+&version 2.8.3
