diff --git a/Network/Wai/Handler/Warp/Request.hs b/Network/Wai/Handler/Warp/Request.hs
--- a/Network/Wai/Handler/Warp/Request.hs
+++ b/Network/Wai/Handler/Warp/Request.hs
@@ -25,17 +25,20 @@
 import Network.Wai.Handler.Warp.ReadInt
 import Network.Wai.Handler.Warp.Types
 import Prelude hiding (lines)
+import qualified Network.Wai.Handler.Warp.Timeout as Timeout
 
 -- FIXME come up with good values here
 maxTotalHeaderLength :: Int
 maxTotalHeaderLength = 50 * 1024
 
-parseRequest :: Connection -> Port -> SockAddr
+parseRequest :: Connection
+             -> Timeout.Handle
+             -> Port -> SockAddr
              -> Source (ResourceT IO) ByteString
              -> ResourceT IO (Request, IO (ResumableSource (ResourceT IO) ByteString))
-parseRequest conn port remoteHost' src1 = do
+parseRequest conn timeoutHandle port remoteHost' src1 = do
     (src2, headers') <- src1 $$+ takeHeaders
-    parseRequest' conn port headers' remoteHost' src2
+    parseRequest' conn timeoutHandle port headers' remoteHost' src2
 
 handleExpect :: Connection
              -> H.HttpVersion
@@ -53,13 +56,14 @@
 
 -- | Parse a set of header lines and body into a 'Request'.
 parseRequest' :: Connection
+              -> Timeout.Handle
               -> Port
               -> [ByteString]
               -> SockAddr
               -> ResumableSource (ResourceT IO) ByteString -- FIXME was buffered
               -> ResourceT IO (Request, IO (ResumableSource (ResourceT IO) ByteString))
-parseRequest' _ _ [] _ _ = throwIO $ NotEnoughLines []
-parseRequest' conn port (firstLine:otherLines) remoteHost' src = do
+parseRequest' _ _ _ [] _ _ = throwIO $ NotEnoughLines []
+parseRequest' conn timeoutHandle port (firstLine:otherLines) remoteHost' src = do
     (method, rpath', gets, httpversion) <- parseFirst firstLine
     let (host',rpath)
             | S.null rpath' = ("", "/")
@@ -97,7 +101,16 @@
             , requestHeaders = heads
             , isSecure = False
             , remoteHost = remoteHost'
-            , requestBody = rbody
+            , requestBody = do
+                -- Timeout handling was paused after receiving the full request
+                -- headers. Now we need to resume it to avoid a slowloris
+                -- attack during request body sending.
+                liftIO $ Timeout.resume timeoutHandle
+                -- As soon as we finish receiving the request body, whether
+                -- because the application is not interested in more bytes, or
+                -- because there is no more data available, pause the timeout
+                -- handler again.
+                addCleanup (const $ liftIO $ Timeout.pause timeoutHandle) rbody
             , vault = mempty
 #if MIN_VERSION_wai(1, 4, 0)
             , requestBodyLength =
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
@@ -206,7 +206,7 @@
                     bracket_ onOpen onClose $
 
                     -- Actually serve this connection.
-                    serveConnection set cleaner port app conn addr
+                    serveConnection th set cleaner port app conn addr
   where
     -- FIXME: only IOEception is caught. What about other exceptions?
     getConnLoop = getConn `catch` \(e :: IOException) -> do
@@ -228,10 +228,11 @@
                 f
             Just tm -> f tm
 
-serveConnection :: Settings
+serveConnection :: T.Handle
+                -> Settings
                 -> Cleaner
                 -> Port -> Application -> Connection -> SockAddr-> IO ()
-serveConnection settings cleaner port app conn remoteHost' =
+serveConnection timeoutHandle settings cleaner port app conn remoteHost' =
     runResourceT serveConnection'
   where
     innerRunResourceT
@@ -243,7 +244,7 @@
     serveConnection' = serveConnection'' $ connSource conn th
 
     serveConnection'' fromClient = do
-        (env, getSource) <- parseRequest conn port remoteHost' fromClient
+        (env, getSource) <- parseRequest conn timeoutHandle port remoteHost' fromClient
         case settingsIntercept settings env of
             Nothing -> do
                 -- Let the application run for as long as it wants
diff --git a/warp.cabal b/warp.cabal
--- a/warp.cabal
+++ b/warp.cabal
@@ -1,5 +1,5 @@
 Name:                warp
-Version:             1.3.8.2
+Version:             1.3.8.3
 Synopsis:            A fast, light-weight web server for WAI applications.
 License:             MIT
 License-file:        LICENSE
@@ -20,6 +20,10 @@
 Flag network-bytestring
     Default: False
 
+Flag allow-sendfilefd
+    Description: Allow use of sendfileFd (not available on GNU/kFreeBSD)
+    Default:     True
+
 Library
   Build-Depends:     base                      >= 3        && < 5
                    , blaze-builder             >= 0.2.1.4  && < 0.4
@@ -53,7 +57,7 @@
                      Network.Wai.Handler.Warp.Types
                      Paths_warp
   Ghc-Options:       -Wall
-  if os(linux) || os(freebsd) || os(darwin)
+  if (os(linux) || os(freebsd) || os(darwin)) && flag(allow-sendfilefd)
       Cpp-Options:   -DSENDFILEFD
       Build-Depends: hashable
       Other-modules: Network.Wai.Handler.Warp.FdCache
@@ -92,7 +96,7 @@
     -- Yes, this means that the test suite will no longer work on Windows.
     -- Unfortunately there is a bug in older versions of cabal, and this conditional
     -- will therefore break older systems.
-  --if os(linux) || os(freebsd) || os(darwin)
+  --if (os(linux) || os(freebsd) || os(darwin)) && flag(allow-sendfilefd)
     Cpp-Options:   -DSENDFILEFD
     Build-Depends: unix
                    , hashable
