diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,13 @@
 # ChangeLog for http2
 
+## 5.3.5
+
+* Using `http-semantics` v0.3.
+* Deprecating `numberOfWorkers`.
+* Removing `unliftio`.
+* Avoid `undefined` in client.
+  [#146](https://github.com/kazu-yamamoto/http2/pull/146)
+
 ## 5.3.4
 
 * Support stream cancellation
diff --git a/Network/HPACK/HeaderBlock/Decode.hs b/Network/HPACK/HeaderBlock/Decode.hs
--- a/Network/HPACK/HeaderBlock/Decode.hs
+++ b/Network/HPACK/HeaderBlock/Decode.hs
@@ -14,6 +14,7 @@
     decodeSimple, -- testing
 ) where
 
+import Control.Exception (catch, throwIO)
 import Data.Array.Base (unsafeRead, unsafeWrite)
 import qualified Data.Array.IO as IOA
 import qualified Data.Array.Unsafe as Unsafe
@@ -22,7 +23,6 @@
 import Data.Char (isUpper)
 import Network.ByteOrder
 import Network.HTTP.Semantics
-import UnliftIO.Exception (catch, throwIO)
 
 import Imports hiding (empty)
 import Network.HPACK.Builder
diff --git a/Network/HPACK/HeaderBlock/Encode.hs b/Network/HPACK/HeaderBlock/Encode.hs
--- a/Network/HPACK/HeaderBlock/Encode.hs
+++ b/Network/HPACK/HeaderBlock/Encode.hs
@@ -8,6 +8,8 @@
     encodeS,
 ) where
 
+import Control.Exception (bracket, throwIO)
+import qualified Control.Exception as E
 import qualified Data.ByteString as BS
 import Data.ByteString.Internal (create)
 import Data.IORef
@@ -16,8 +18,6 @@
 import Foreign.Ptr (minusPtr)
 import Network.ByteOrder
 import Network.HTTP.Semantics
-import UnliftIO.Exception (bracket, throwIO)
-import qualified UnliftIO.Exception as E
 
 import Imports
 import Network.HPACK.HeaderBlock.Integer
diff --git a/Network/HPACK/Huffman/Decode.hs b/Network/HPACK/Huffman/Decode.hs
--- a/Network/HPACK/Huffman/Decode.hs
+++ b/Network/HPACK/Huffman/Decode.hs
@@ -9,11 +9,11 @@
     GCBuffer,
 ) where
 
+import Control.Exception (throwIO)
 import Data.Array (Array, listArray)
 import Data.Array.Base (unsafeAt)
 import qualified Data.ByteString as BS
 import Network.ByteOrder
-import UnliftIO.Exception (throwIO)
 
 import Imports
 import Network.HPACK.Huffman.Bit
diff --git a/Network/HPACK/Huffman/Encode.hs b/Network/HPACK/Huffman/Encode.hs
--- a/Network/HPACK/Huffman/Encode.hs
+++ b/Network/HPACK/Huffman/Encode.hs
@@ -6,6 +6,7 @@
     encodeHuffman,
 ) where
 
+import Control.Exception (throwIO)
 import Data.Array.Base (unsafeAt)
 import Data.Array.IArray (listArray)
 import Data.Array.Unboxed (UArray)
@@ -13,7 +14,6 @@
 import Foreign.Ptr (minusPtr, plusPtr)
 import Foreign.Storable (poke)
 import Network.ByteOrder hiding (copy)
-import UnliftIO.Exception (throwIO)
 
 import Imports
 import Network.HPACK.Huffman.Params (idxEos)
diff --git a/Network/HPACK/Table/Dynamic.hs b/Network/HPACK/Table/Dynamic.hs
--- a/Network/HPACK/Table/Dynamic.hs
+++ b/Network/HPACK/Table/Dynamic.hs
@@ -24,11 +24,11 @@
     getRevIndex,
 ) where
 
+import Control.Exception (throwIO)
 import Data.Array.Base (unsafeRead, unsafeWrite)
 import Data.Array.IO (IOArray, newArray)
 import qualified Data.ByteString.Char8 as BS
 import Data.IORef
-import UnliftIO.Exception (throwIO)
 
 import Imports
 import Network.HPACK.Huffman
diff --git a/Network/HPACK/Table/RevIndex.hs b/Network/HPACK/Table/RevIndex.hs
--- a/Network/HPACK/Table/RevIndex.hs
+++ b/Network/HPACK/Table/RevIndex.hs
@@ -17,6 +17,8 @@
 import Data.Array.Base (unsafeAt)
 import Data.Function (on)
 import Data.IORef
+import Data.List.NonEmpty (NonEmpty (..))
+import qualified Data.List.NonEmpty as NE
 import Data.Map.Strict (Map)
 import qualified Data.Map.Strict as M
 import Network.HTTP.Semantics
@@ -64,15 +66,15 @@
     toEnt (k, xs) = (tokenIx $ toToken $ foldedCase k, m)
       where
         m = case xs of
-            [] -> error "staticRevIndex"
-            [("", i)] -> StaticEntry i Nothing
-            (_, i) : _ ->
-                let vs = M.fromList xs
+            ("", i) :| [] -> StaticEntry i Nothing
+            (_, i) :| _ ->
+                let vs = M.fromList $ NE.toList xs
                  in StaticEntry i (Just vs)
-    zs = map extract $ groupBy ((==) `on` fst) lst
+    zs = map extract $ NE.groupBy ((==) `on` fst) lst
       where
         lst = zipWith (\(k, v) i -> (k, (v, i))) staticTableList $ map SIndex [1 ..]
-        extract xs = (fst (head xs), map snd xs)
+
+        extract xs = (fst (NE.head xs), NE.map snd xs)
 
 {-# INLINE lookupStaticRevIndex #-}
 lookupStaticRevIndex
diff --git a/Network/HPACK/Types.hs b/Network/HPACK/Types.hs
--- a/Network/HPACK/Types.hs
+++ b/Network/HPACK/Types.hs
@@ -22,8 +22,9 @@
     BufferOverrun (..),
 ) where
 
+import Control.Exception as E
+import Data.Typeable
 import Network.ByteOrder (Buffer, BufferOverrun (..), BufferSize)
-import UnliftIO.Exception as E
 
 import Imports
 
diff --git a/Network/HTTP2/Client.hs b/Network/HTTP2/Client.hs
--- a/Network/HTTP2/Client.hs
+++ b/Network/HTTP2/Client.hs
@@ -13,8 +13,8 @@
 -- > import qualified Data.ByteString.Char8 as C8
 -- > import Network.HTTP.Types
 -- > import Network.Run.TCP (runTCPClient) -- network-run
--- > import UnliftIO.Async -- unliftio
--- > import qualified UnliftIO.Exception as E -- unliftio
+-- > import Control.Concurrent.Async -- unliftio
+-- > import qualified Control.Exception as E -- unliftio
 -- >
 -- > import Network.HTTP2.Client
 -- >
diff --git a/Network/HTTP2/Client/Run.hs b/Network/HTTP2/Client/Run.hs
--- a/Network/HTTP2/Client/Run.hs
+++ b/Network/HTTP2/Client/Run.hs
@@ -5,7 +5,10 @@
 
 module Network.HTTP2.Client.Run where
 
-import Control.Concurrent.STM (check)
+import Control.Concurrent
+import Control.Concurrent.Async
+import Control.Concurrent.STM
+import Control.Exception
 import qualified Data.ByteString.UTF8 as UTF8
 import Data.IORef
 import Data.IP (IPv6)
@@ -15,10 +18,6 @@
 import Network.HTTP.Semantics.IO
 import Network.Socket (SockAddr)
 import Text.Read (readMaybe)
-import UnliftIO.Async
-import UnliftIO.Concurrent
-import UnliftIO.Exception
-import UnliftIO.STM
 
 import Imports
 import Network.HTTP2.Frame
@@ -142,7 +141,7 @@
 
 runH2 :: Config -> Context -> IO a -> IO a
 runH2 conf ctx runClient = do
-    stopAfter mgr (clientResult <$> race runBackgroundThreads runClient) $ \res ->
+    stopAfter mgr runAll $ \res ->
         closeAllStreams (oddStreamTable ctx) (evenStreamTable ctx) res
   where
     mgr = threadManager ctx
@@ -152,9 +151,19 @@
         labelMe "H2 runBackgroundThreads"
         concurrently_ runReceiver runSender
 
-    clientResult :: Either () a -> a
-    clientResult (Left ()) = undefined -- unreachable
-    clientResult (Right a) = a
+    -- Run the background threads and client concurrently. If the client
+    -- finishes first, cancel the background threads. If the background
+    -- threads finish first, wait for the client.
+    runAll = do
+        withAsync runBackgroundThreads $ \runningBackgroundThreads ->
+            withAsync runClient $ \runningClient -> do
+                result <- waitEither runningBackgroundThreads runningClient
+                case result of
+                    Right clientResult -> do
+                        cancel runningBackgroundThreads
+                        return clientResult
+                    Left () -> do
+                        wait runningClient
 
 sendRequest
     :: Config
@@ -200,11 +209,8 @@
     (mnext, mtbq) <- case outObjBody of
         OutBodyNone -> return (Nothing, Nothing)
         OutBodyFile (FileSpec path fileoff bytecount) -> do
-            (pread, closerOrRefresher) <- confPositionReadMaker path
-            refresh <- case closerOrRefresher of
-                Closer closer -> timeoutClose threadManager closer
-                Refresher refresher -> return refresher
-            let next = fillFileBodyGetNext pread fileoff bytecount refresh
+            (pread, sentinel) <- confPositionReadMaker path
+            let next = fillFileBodyGetNext pread fileoff bytecount sentinel
             return (Just next, Nothing)
         OutBodyBuilder builder -> do
             let next = fillBuilderBodyGetNext builder
diff --git a/Network/HTTP2/Frame/Decode.hs b/Network/HTTP2/Frame/Decode.hs
--- a/Network/HTTP2/Frame/Decode.hs
+++ b/Network/HTTP2/Frame/Decode.hs
@@ -24,12 +24,12 @@
     decodeContinuationFrame,
 ) where
 
+import Control.Exception (Exception)
 import Data.Array (Array, listArray, (!))
 import qualified Data.ByteString as BS
 import Foreign.Ptr (Ptr, plusPtr)
 import qualified Network.ByteOrder as N
 import System.IO.Unsafe (unsafeDupablePerformIO)
-import UnliftIO.Exception (Exception)
 
 import Imports
 import Network.HTTP2.Frame.Types
diff --git a/Network/HTTP2/H2/Context.hs b/Network/HTTP2/H2/Context.hs
--- a/Network/HTTP2/H2/Context.hs
+++ b/Network/HTTP2/H2/Context.hs
@@ -4,13 +4,13 @@
 
 module Network.HTTP2.H2.Context where
 
+import Control.Concurrent.STM
+import Control.Exception
+import qualified Control.Exception as E
 import Data.IORef
 import Network.Control
 import Network.Socket (SockAddr)
 import qualified System.TimeManager as T
-import UnliftIO.Exception
-import qualified UnliftIO.Exception as E
-import UnliftIO.STM
 
 import Imports hiding (insert)
 import Network.HPACK
diff --git a/Network/HTTP2/H2/HPACK.hs b/Network/HTTP2/H2/HPACK.hs
--- a/Network/HTTP2/H2/HPACK.hs
+++ b/Network/HTTP2/H2/HPACK.hs
@@ -10,10 +10,10 @@
     fixHeaders,
 ) where
 
+import qualified Control.Exception as E
 import Network.ByteOrder
 import Network.HTTP.Semantics
 import Network.HTTP.Types
-import qualified UnliftIO.Exception as E
 
 import Imports
 import Network.HPACK
diff --git a/Network/HTTP2/H2/Manager.hs b/Network/HTTP2/H2/Manager.hs
--- a/Network/HTTP2/H2/Manager.hs
+++ b/Network/HTTP2/H2/Manager.hs
@@ -15,14 +15,14 @@
     waitCounter0,
 ) where
 
+import Control.Concurrent
+import Control.Concurrent.STM
+import Control.Exception
+import qualified Control.Exception as E
 import Data.Foldable
 import Data.Map (Map)
 import qualified Data.Map.Strict as Map
 import qualified System.TimeManager as T
-import UnliftIO.Concurrent
-import UnliftIO.Exception
-import qualified UnliftIO.Exception as E
-import UnliftIO.STM
 
 import Imports
 
@@ -87,7 +87,7 @@
 stopAfter :: Manager -> IO a -> (Maybe SomeException -> IO ()) -> IO a
 stopAfter (Manager q _ _) action cleanup = do
     mask $ \unmask -> do
-        ma <- trySyncOrAsync $ unmask action
+        ma <- try $ unmask action
         signalTimeoutsDisabled <- newEmptyMVar
         atomically $
             writeTQueue q $
@@ -114,13 +114,13 @@
 forkManagedUnmask
     :: Manager -> String -> ((forall x. IO x -> IO x) -> IO ()) -> IO ()
 forkManagedUnmask mgr label io =
-    void $ mask_ $ forkIOWithUnmask $ \unmask -> E.handleSyncOrAsync handler $ do
+    void $ mask_ $ forkIOWithUnmask $ \unmask -> E.handle handler $ do
         labelMe label
         addMyId mgr
         incCounter mgr
         -- We catch the exception and do not rethrow it: we don't want the
         -- exception printed to stderr.
-        io unmask `catchSyncOrAsync` \(_e :: SomeException) -> return ()
+        io unmask `catch` \(_e :: SomeException) -> return ()
         deleteMyId mgr
         decCounter mgr
   where
@@ -205,4 +205,4 @@
 waitCounter0 :: Manager -> IO ()
 waitCounter0 (Manager _ cnt _) = atomically $ do
     n <- readTVar cnt
-    checkSTM (n < 1)
+    check (n < 1)
diff --git a/Network/HTTP2/H2/Queue.hs b/Network/HTTP2/H2/Queue.hs
--- a/Network/HTTP2/H2/Queue.hs
+++ b/Network/HTTP2/H2/Queue.hs
@@ -2,7 +2,7 @@
 
 module Network.HTTP2.H2.Queue where
 
-import UnliftIO.STM
+import Control.Concurrent.STM
 
 import Network.HTTP2.H2.Types
 
diff --git a/Network/HTTP2/H2/Receiver.hs b/Network/HTTP2/H2/Receiver.hs
--- a/Network/HTTP2/H2/Receiver.hs
+++ b/Network/HTTP2/H2/Receiver.hs
@@ -8,6 +8,9 @@
     frameReceiver,
 ) where
 
+import Control.Concurrent
+import Control.Concurrent.STM
+import qualified Control.Exception as E
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Char8 as C8
 import qualified Data.ByteString.Short as Short
@@ -15,9 +18,6 @@
 import Data.IORef
 import Network.Control
 import Network.HTTP.Semantics
-import UnliftIO.Concurrent
-import qualified UnliftIO.Exception as E
-import UnliftIO.STM
 
 import Imports hiding (delete, insert)
 import Network.HTTP2.Frame
@@ -58,6 +58,9 @@
                 loop
 
     sendGoaway se
+        | Just GoAwayIsSent <- E.fromException se = do
+            waitCounter0 threadManager
+            enqueueControl controlQ $ CFinish GoAwayIsSent
         | Just ConnectionIsClosed <- E.fromException se = do
             waitCounter0 threadManager
             enqueueControl controlQ $ CFinish ConnectionIsClosed
diff --git a/Network/HTTP2/H2/Sender.hs b/Network/HTTP2/H2/Sender.hs
--- a/Network/HTTP2/H2/Sender.hs
+++ b/Network/HTTP2/H2/Sender.hs
@@ -7,14 +7,14 @@
     frameSender,
 ) where
 
+import Control.Concurrent.STM
+import qualified Control.Exception as E
 import Data.IORef (modifyIORef', readIORef, writeIORef)
 import Data.IntMap.Strict (IntMap)
 import Foreign.Ptr (minusPtr, plusPtr)
 import Network.ByteOrder
 import Network.HTTP.Semantics.Client
 import Network.HTTP.Semantics.IO
-import qualified UnliftIO.Exception as E
-import UnliftIO.STM
 
 import Imports
 import Network.HPACK (setLimitForEncoding, toTokenHeaderTable)
@@ -104,7 +104,7 @@
                     waitConnectionWindowSize ctx
                     isEmptyO <- isEmptyTQueue outputQ
                     if isEmptyO
-                        then if off /= 0 then return Flush else retrySTM
+                        then if off /= 0 then return Flush else retry
                         else O <$> readTQueue outputQ
                 else C <$> readTQueue controlQ
 
diff --git a/Network/HTTP2/H2/Stream.hs b/Network/HTTP2/H2/Stream.hs
--- a/Network/HTTP2/H2/Stream.hs
+++ b/Network/HTTP2/H2/Stream.hs
@@ -6,16 +6,15 @@
 
 module Network.HTTP2.H2.Stream where
 
+import Control.Concurrent
+import Control.Concurrent.STM
+import Control.Exception
 import Control.Monad
-import Control.Monad.STM (throwSTM)
 import Data.IORef
 import Data.Maybe (fromMaybe)
 import Network.Control
 import Network.HTTP.Semantics
 import Network.HTTP.Semantics.IO
-import UnliftIO.Concurrent
-import UnliftIO.Exception
-import UnliftIO.STM
 
 import Network.HTTP2.Frame
 import Network.HTTP2.H2.StreamTable
diff --git a/Network/HTTP2/H2/StreamTable.hs b/Network/HTTP2/H2/StreamTable.hs
--- a/Network/HTTP2/H2/StreamTable.hs
+++ b/Network/HTTP2/H2/StreamTable.hs
@@ -33,11 +33,11 @@
 
 import Control.Concurrent
 import Control.Concurrent.STM
+import Control.Exception
 import Data.IntMap.Strict (IntMap)
 import qualified Data.IntMap.Strict as IntMap
 import Network.Control (LRUCache)
 import qualified Network.Control as LRUCache
-import UnliftIO.Exception
 
 import Imports
 import Network.HTTP2.H2.Types (Stream (..))
diff --git a/Network/HTTP2/H2/Sync.hs b/Network/HTTP2/H2/Sync.hs
--- a/Network/HTTP2/H2/Sync.hs
+++ b/Network/HTTP2/H2/Sync.hs
@@ -3,8 +3,8 @@
 module Network.HTTP2.H2.Sync (prepareSync, syncWithSender) where
 
 import Control.Concurrent
+import Control.Concurrent.STM
 import Network.HTTP.Semantics.IO
-import UnliftIO.STM
 
 import Network.HTTP2.H2.Context
 import Network.HTTP2.H2.Queue
@@ -96,4 +96,4 @@
 waitStreaming :: TBQueue a -> IO ()
 waitStreaming tbq = atomically $ do
     isEmpty <- isEmptyTBQueue tbq
-    checkSTM (not isEmpty)
+    check (not isEmpty)
diff --git a/Network/HTTP2/H2/Types.hs b/Network/HTTP2/H2/Types.hs
--- a/Network/HTTP2/H2/Types.hs
+++ b/Network/HTTP2/H2/Types.hs
@@ -5,6 +5,10 @@
 
 module Network.HTTP2.H2.Types where
 
+import Control.Concurrent
+import Control.Concurrent.STM
+import Control.Exception (SomeException)
+import qualified Control.Exception as E
 import Data.IORef
 import Data.Typeable
 import Network.Control
@@ -13,10 +17,6 @@
 import Network.Socket hiding (Stream)
 import System.IO.Unsafe
 import qualified System.TimeManager as T
-import UnliftIO.Concurrent
-import UnliftIO.Exception (SomeException)
-import qualified UnliftIO.Exception as E
-import UnliftIO.STM
 
 import Imports
 import Network.HPACK
diff --git a/Network/HTTP2/H2/Window.hs b/Network/HTTP2/H2/Window.hs
--- a/Network/HTTP2/H2/Window.hs
+++ b/Network/HTTP2/H2/Window.hs
@@ -3,11 +3,11 @@
 
 module Network.HTTP2.H2.Window where
 
+import Control.Concurrent.STM
+import qualified Control.Exception as E
 import qualified Data.ByteString as BS
 import Data.IORef
 import Network.Control
-import qualified UnliftIO.Exception as E
-import UnliftIO.STM
 
 import Imports
 import Network.HTTP2.Frame
@@ -27,12 +27,12 @@
 waitStreamWindowSize :: Stream -> IO ()
 waitStreamWindowSize Stream{streamTxFlow} = atomically $ do
     w <- txWindowSize <$> readTVar streamTxFlow
-    checkSTM (w > 0)
+    check (w > 0)
 
 waitConnectionWindowSize :: Context -> STM ()
 waitConnectionWindowSize Context{txFlow} = do
     w <- txWindowSize <$> readTVar txFlow
-    checkSTM (w > 0)
+    check (w > 0)
 
 ----------------------------------------------------------------
 -- Receiving window update
diff --git a/Network/HTTP2/Server.hs b/Network/HTTP2/Server.hs
--- a/Network/HTTP2/Server.hs
+++ b/Network/HTTP2/Server.hs
@@ -7,7 +7,7 @@
 -- > {-# LANGUAGE OverloadedStrings #-}
 -- > module Main (main) where
 -- >
--- > import qualified UnliftIO.Exception as E
+-- > import qualified Control.Exception as E
 -- > import Data.ByteString.Builder (byteString)
 -- > import Network.HTTP.Types (ok200)
 -- > import Network.Run.TCP (runTCPServer) -- network-run
diff --git a/Network/HTTP2/Server/Run.hs b/Network/HTTP2/Server/Run.hs
--- a/Network/HTTP2/Server/Run.hs
+++ b/Network/HTTP2/Server/Run.hs
@@ -4,6 +4,7 @@
 
 module Network.HTTP2.Server.Run where
 
+import Control.Concurrent.Async (concurrently_)
 import Control.Concurrent.STM
 import Imports
 import Network.Control (defaultMaxData)
@@ -11,7 +12,6 @@
 import Network.HTTP.Semantics.Server
 import Network.HTTP.Semantics.Server.Internal
 import Network.Socket (SockAddr)
-import UnliftIO.Async (concurrently_)
 
 import Network.HTTP2.Frame
 import Network.HTTP2.H2
@@ -20,13 +20,15 @@
 -- | Server configuration
 data ServerConfig = ServerConfig
     { numberOfWorkers :: Int
-    -- ^ The number of workers
+    -- ^ Deprecated field.
     , connectionWindowSize :: WindowSize
     -- ^ The window size of incoming streams
     , settings :: Settings
     -- ^ Settings
     }
     deriving (Eq, Show)
+
+{-# DEPRECATED numberOfWorkers "No effect anymore" #-}
 
 -- | The default server config.
 --
diff --git a/Network/HTTP2/Server/Worker.hs b/Network/HTTP2/Server/Worker.hs
--- a/Network/HTTP2/Server/Worker.hs
+++ b/Network/HTTP2/Server/Worker.hs
@@ -6,6 +6,7 @@
     worker,
 ) where
 
+import Control.Concurrent.STM
 import Data.IORef
 import Network.HTTP.Semantics
 import Network.HTTP.Semantics.IO
@@ -13,7 +14,6 @@
 import Network.HTTP.Semantics.Server.Internal
 import Network.HTTP.Types
 import qualified System.TimeManager as T
-import UnliftIO.STM
 
 import Imports hiding (insert)
 import Network.HTTP2.Frame
@@ -56,7 +56,7 @@
     -- Checking if all push are done.
     waiter lim tvar = atomically $ do
         n <- readTVar tvar
-        checkSTM (n >= lim)
+        check (n >= lim)
     push _ [] n = return (n :: Int)
     push tvar (pp : pps) n = do
         forkManaged threadManager "H2 server push" $ do
@@ -111,11 +111,8 @@
     (mnext, mtbq) <- case outObjBody of
         OutBodyNone -> return (Nothing, Nothing)
         OutBodyFile (FileSpec path fileoff bytecount) -> do
-            (pread, closerOrRefresher) <- confPositionReadMaker path
-            refresh <- case closerOrRefresher of
-                Closer closer -> timeoutClose threadManager closer
-                Refresher refresher -> return refresher
-            let next = fillFileBodyGetNext pread fileoff bytecount refresh
+            (pread, sentinel) <- confPositionReadMaker path
+            let next = fillFileBodyGetNext pread fileoff bytecount sentinel
             return (Just next, Nothing)
         OutBodyBuilder builder -> do
             let next = fillBuilderBodyGetNext builder
diff --git a/bench-hpack/Main.hs b/bench-hpack/Main.hs
--- a/bench-hpack/Main.hs
+++ b/bench-hpack/Main.hs
@@ -2,10 +2,10 @@
 
 module Main where
 
+import Control.Exception
 import Criterion.Main
 import Data.ByteString (ByteString)
 import Network.HPACK
-import UnliftIO.Exception
 
 ----------------------------------------------------------------
 
diff --git a/http2.cabal b/http2.cabal
--- a/http2.cabal
+++ b/http2.cabal
@@ -1,6 +1,6 @@
 cabal-version:      >=1.10
 name:               http2
-version:            5.3.4
+version:            5.3.5
 license:            BSD3
 license-file:       LICENSE
 maintainer:         Kazu Yamamoto <kazu@iij.ad.jp>
@@ -116,7 +116,7 @@
         bytestring >=0.10,
         case-insensitive >=1.2 && <1.3,
         containers >=0.6,
-        http-semantics >= 0.2.1 && <0.3,
+        http-semantics >= 0.3 && <0.4,
         http-types >=0.12 && <0.13,
         iproute >= 1.7 && < 1.8,
         network >=3.1,
@@ -125,7 +125,6 @@
         stm >=2.5 && <2.6,
         time-manager >=0.1 && <0.2,
         unix-time >=0.4.11 && <0.5,
-        unliftio >=0.2 && <0.3,
         utf8-string >=1.0 && <1.1
 
 executable h2c-client
@@ -142,8 +141,7 @@
         http-types,
         http2,
         network-run >= 0.3 && <0.5,
-        unix-time,
-        unliftio
+        unix-time
 
     if flag(devel)
 
@@ -163,8 +161,7 @@
         crypton,
         http2,
         http-types,
-        network-run,
-        unliftio
+        network-run
 
     if flag(devel)
 
@@ -221,7 +218,6 @@
         http2,
         network-byte-order,
         text,
-        unliftio,
         unordered-containers,
         vector,
         word8
@@ -315,7 +311,6 @@
         network,
         network-run >=0.3.0,
         random,
-        unliftio,
         typed-process
 
 test-suite spec2
@@ -334,8 +329,7 @@
         http-types,
         http2,
         network-run >=0.3.0,
-        typed-process,
-        unliftio
+        typed-process
 
     if flag(h2spec)
 
@@ -365,7 +359,6 @@
         hspec >=1.3,
         http2,
         text,
-        unliftio,
         unordered-containers,
         vector
 
@@ -413,5 +406,4 @@
         criterion,
         http2,
         network-byte-order,
-        stm,
-        unliftio
+        stm
diff --git a/test-hpack/HPACKDecode.hs b/test-hpack/HPACKDecode.hs
--- a/test-hpack/HPACKDecode.hs
+++ b/test-hpack/HPACKDecode.hs
@@ -12,13 +12,13 @@
 #if __GLASGOW_HASKELL__ < 709
 import Control.Applicative ((<$>))
 #endif
+import Control.Exception
 import Control.Monad (when)
 import qualified Data.ByteString.Base16 as B16
 import qualified Data.ByteString.Char8 as B8
 import Data.List (sort)
 import Network.HPACK
 import Network.HPACK.Table
-import UnliftIO.Exception
 
 import JSON
 
diff --git a/test/HPACK/EncodeSpec.hs b/test/HPACK/EncodeSpec.hs
--- a/test/HPACK/EncodeSpec.hs
+++ b/test/HPACK/EncodeSpec.hs
@@ -5,12 +5,12 @@
 #if __GLASGOW_HASKELL__ < 709
 import Control.Applicative ((<$>))
 #endif
+import qualified Control.Exception as E
 import Data.Bits
 import qualified Data.ByteString as BS
 import Data.Maybe (fromMaybe)
 import Network.HPACK
 import Test.Hspec
-import qualified UnliftIO.Exception as E
 
 spec :: Spec
 spec = do
diff --git a/test/HTTP2/ClientSpec.hs b/test/HTTP2/ClientSpec.hs
--- a/test/HTTP2/ClientSpec.hs
+++ b/test/HTTP2/ClientSpec.hs
@@ -6,6 +6,7 @@
 module HTTP2.ClientSpec (spec) where
 
 import Control.Concurrent
+import qualified Control.Exception as E
 import Control.Monad
 import Data.ByteString.Builder (byteString)
 import Data.Foldable (for_)
@@ -18,7 +19,6 @@
 import System.Random
 import System.Timeout (timeout)
 import Test.Hspec
-import qualified UnliftIO.Exception as E
 
 import Network.HTTP2.Client
 import qualified Network.HTTP2.Server as S
diff --git a/test/HTTP2/ServerSpec.hs b/test/HTTP2/ServerSpec.hs
--- a/test/HTTP2/ServerSpec.hs
+++ b/test/HTTP2/ServerSpec.hs
@@ -6,8 +6,12 @@
 module HTTP2.ServerSpec (spec) where
 
 import Control.Concurrent
+-- cryptonite
+
+import Control.Concurrent.Async
+import qualified Control.Exception as E
 import Control.Monad
-import Crypto.Hash (Context, SHA1) -- cryptonite
+import Crypto.Hash (Context, SHA1)
 import qualified Crypto.Hash as CH
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as B
@@ -23,8 +27,6 @@
 import System.IO.Unsafe
 import System.Random
 import Test.Hspec
-import UnliftIO.Async
-import qualified UnliftIO.Exception as E
 
 import Network.HPACK
 import Network.HPACK.Internal
diff --git a/test2/ServerSpec.hs b/test2/ServerSpec.hs
--- a/test2/ServerSpec.hs
+++ b/test2/ServerSpec.hs
@@ -4,13 +4,13 @@
 module ServerSpec (spec) where
 
 import Control.Concurrent
+import qualified Control.Exception as E
 import Data.ByteString.Builder (byteString)
 import Network.HTTP.Types
 import Network.Run.TCP
 import System.Exit
 import System.Process.Typed
 import Test.Hspec
-import qualified UnliftIO.Exception as E
 
 import Network.HTTP2.Server
 
diff --git a/util/Client.hs b/util/Client.hs
--- a/util/Client.hs
+++ b/util/Client.hs
@@ -4,14 +4,14 @@
 
 module Client where
 
+import Control.Concurrent.Async
+import qualified Control.Exception as E
 import Control.Monad
 import qualified Data.ByteString.Char8 as C8
 import Data.UnixTime
 import Foreign.C.Types
 import Network.HTTP.Types
 import Text.Printf
-import UnliftIO.Async
-import qualified UnliftIO.Exception as E
 
 import Network.HTTP2.Client
 
diff --git a/util/h2c-client.hs b/util/h2c-client.hs
--- a/util/h2c-client.hs
+++ b/util/h2c-client.hs
@@ -4,13 +4,13 @@
 module Main where
 
 import Control.Concurrent
+import qualified Control.Exception as E
 import qualified Data.ByteString.Char8 as C8
 import Network.HTTP2.Client
 import Network.Run.TCP (runTCPClient)
 import System.Console.GetOpt
 import System.Environment
 import System.Exit
-import qualified UnliftIO.Exception as E
 
 import Client
 import Monitor
diff --git a/util/h2c-server.hs b/util/h2c-server.hs
--- a/util/h2c-server.hs
+++ b/util/h2c-server.hs
@@ -5,12 +5,12 @@
 module Main (main) where
 
 import Control.Concurrent
+import qualified Control.Exception as E
 import Network.HTTP2.Server
 import Network.Run.TCP
 import System.Console.GetOpt
 import System.Environment
 import System.Exit
-import qualified UnliftIO.Exception as E
 
 import Monitor
 import Server
