diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,8 @@
+## 3.2.11.1
+
+* Move exception handling to top of thread (fixes
+  [#613](https://github.com/yesodweb/wai/issues/613))
+
 ## 3.2.11
 
 * Fixing 10 HTTP2 bugs pointed out by h2spec v2.
diff --git a/Network/Wai/Handler/Warp/Run.hs b/Network/Wai/Handler/Warp/Run.hs
--- a/Network/Wai/Handler/Warp/Run.hs
+++ b/Network/Wai/Handler/Warp/Run.hs
@@ -263,51 +263,53 @@
      -> Counter
      -> InternalInfo0
      -> IO ()
-fork set mkConn addr app counter ii0 = settingsFork set $ \ unmask ->
+fork set mkConn addr app counter ii0 = settingsFork set $ \unmask ->
+    -- Call the user-supplied on exception code if any
+    -- exceptions are thrown.
+    handle (settingsOnException set Nothing) .
     -- Allocate a new IORef indicating whether the connection has been
     -- closed, to avoid double-freeing a connection
     withClosedRef $ \ref ->
-
-    -- Run the connection maker to get a new connection, and ensure
-    -- that the connection is closed. If the mkConn call throws an
-    -- exception, we will leak the connection. If the mkConn call is
-    -- vulnerable to attacks (e.g., Slowloris), we do nothing to
-    -- protect the server. It is therefore vital that mkConn is well
-    -- vetted.
-    --
-    -- We grab the connection before registering timeouts since the
-    -- timeouts will be useless during connection creation, due to the
-    -- fact that async exceptions are still masked.
-    bracket mkConn (\(conn, _) -> closeConn ref conn `finally` connFree conn)
-    $ \(conn, transport) ->
-
-    -- We need to register a timeout handler for this thread, and
-    -- cancel that handler as soon as we exit. We additionally close
-    -- the connection immediately in case the child thread catches the
-    -- async exception or performs some long-running cleanup action.
-    bracket (T.registerKillThread (timeoutManager0 ii0) (closeConn ref conn)) T.cancel $ \th ->
-
-    let ii1 = toInternalInfo1 ii0 th
-        -- We now have fully registered a connection close handler
-        -- in the case of all exceptions, so it is safe to one
-        -- again allow async exceptions.
-    in unmask .
-       -- Call the user-supplied on exception code if any
-       -- exceptions are thrown.
-       handle (settingsOnException set Nothing) .
-
-       -- Call the user-supplied code for connection open and close events
-       bracket (onOpen addr) (onClose addr) $ \goingon ->
-
-       -- Actually serve this connection.
-       -- bracket with closeConn above ensures the connection is closed.
-       when goingon $ serveConnection conn ii1 addr transport set app
+        -- Run the connection maker to get a new connection, and ensure
+        -- that the connection is closed. If the mkConn call throws an
+        -- exception, we will leak the connection. If the mkConn call is
+        -- vulnerable to attacks (e.g., Slowloris), we do nothing to
+        -- protect the server. It is therefore vital that mkConn is well
+        -- vetted.
+        --
+        -- We grab the connection before registering timeouts since the
+        -- timeouts will be useless during connection creation, due to the
+        -- fact that async exceptions are still masked.
+        bracket mkConn (cleanUp ref) (serve unmask ref)
   where
     withClosedRef inner = newIORef False >>= inner
 
     closeConn ref conn = do
         isClosed <- atomicModifyIORef' ref $ \x -> (True, x)
         unless isClosed $ connClose conn
+
+    cleanUp ref (conn, _) = closeConn ref conn `finally` connFree conn
+
+    -- We need to register a timeout handler for this thread, and
+    -- cancel that handler as soon as we exit. We additionally close
+    -- the connection immediately in case the child thread catches the
+    -- async exception or performs some long-running cleanup action.
+    serve unmask ref (conn, transport) = bracket register cancel $ \th -> do
+        let ii1 = toInternalInfo1 ii0 th
+        -- We now have fully registered a connection close handler in
+        -- the case of all exceptions, so it is safe to one again
+        -- allow async exceptions.
+        unmask .
+            -- Call the user-supplied code for connection open and
+            -- close events
+           bracket (onOpen addr) (onClose addr) $ \goingon ->
+           -- Actually serve this connection.  bracket with closeConn
+           -- above ensures the connection is closed.
+           when goingon $ serveConnection conn ii1 addr transport set app
+      where
+        register = T.registerKillThread (timeoutManager0 ii0)
+                                        (closeConn ref conn)
+        cancel   = T.cancel
 
     onOpen adr    = increase counter >> settingsOnOpen  set adr
     onClose adr _ = decrease counter >> settingsOnClose set adr
diff --git a/warp.cabal b/warp.cabal
--- a/warp.cabal
+++ b/warp.cabal
@@ -1,5 +1,5 @@
 Name:                warp
-Version:             3.2.11
+Version:             3.2.11.1
 Synopsis:            A fast, light-weight web server for WAI applications.
 License:             MIT
 License-file:        LICENSE
