diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,10 @@
 # ChangeLog for warp
 
+## 3.4.3
+
+* Waiting untill the number of FDs desreases on EMFILE.
+  [#1009](https://github.com/yesodweb/wai/pull/1009)
+
 ## 3.4.2
 
 * serveConnection is re-exported from the Internal module.
diff --git a/Network/Wai/Handler/Warp/Counter.hs b/Network/Wai/Handler/Warp/Counter.hs
--- a/Network/Wai/Handler/Warp/Counter.hs
+++ b/Network/Wai/Handler/Warp/Counter.hs
@@ -6,6 +6,7 @@
     waitForZero,
     increase,
     decrease,
+    waitForDecreased,
 ) where
 
 import Control.Concurrent.STM
@@ -18,12 +19,19 @@
 newCounter = Counter <$> newTVarIO 0
 
 waitForZero :: Counter -> IO ()
-waitForZero (Counter ref) = atomically $ do
-    x <- readTVar ref
+waitForZero (Counter var) = atomically $ do
+    x <- readTVar var
     when (x > 0) retry
 
+waitForDecreased :: Counter -> IO ()
+waitForDecreased (Counter var) = do
+    n0 <- atomically $ readTVar var
+    atomically $ do
+        n <- readTVar var
+        check (n < n0)
+
 increase :: Counter -> IO ()
-increase (Counter ref) = atomically $ modifyTVar' ref $ \x -> x + 1
+increase (Counter var) = atomically $ modifyTVar' var $ \x -> x + 1
 
 decrease :: Counter -> IO ()
-decrease (Counter ref) = atomically $ modifyTVar' ref $ \x -> x - 1
+decrease (Counter var) = atomically $ modifyTVar' var $ \x -> x - 1
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
@@ -4,6 +4,7 @@
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TupleSections #-}
 {-# OPTIONS_GHC -fno-warn-deprecations #-}
+{-# LANGUAGE MultiWayIf #-}
 
 module Network.Wai.Handler.Warp.Run where
 
@@ -13,7 +14,7 @@
 import qualified Data.ByteString as S
 import Data.IORef (newIORef, readIORef)
 import Data.Streaming.Network (bindPortTCP)
-import Foreign.C.Error (Errno (..), eCONNABORTED)
+import Foreign.C.Error (Errno (..), eCONNABORTED, eMFILE)
 import GHC.IO.Exception (IOErrorType (..), IOException (..))
 import Network.Socket (
     SockAddr,
@@ -305,13 +306,16 @@
         case ex of
             Right x -> return $ Just x
             Left e -> do
-                let eConnAborted = getErrno eCONNABORTED
-                    getErrno (Errno cInt) = cInt
-                if ioe_errno e == Just eConnAborted
-                    then acceptNewConnection
-                    else do
-                        settingsOnException set Nothing $ toException e
-                        return Nothing
+                let getErrno (Errno cInt) = cInt
+                    isErrno err = ioe_errno e == Just (getErrno err)
+                if | isErrno eCONNABORTED -> acceptNewConnection
+                   | isErrno eMFILE -> do
+                       settingsOnException set Nothing $ toException e
+                       waitForDecreased counter
+                       acceptNewConnection
+                   | otherwise -> do
+                       settingsOnException set Nothing $ toException e
+                       return Nothing
 
 -- Fork a new worker thread for this connection maker, and ask for a
 -- function to unmask (i.e., allow async exceptions to be thrown).
diff --git a/warp.cabal b/warp.cabal
--- a/warp.cabal
+++ b/warp.cabal
@@ -1,6 +1,6 @@
 cabal-version:      >=1.10
 name:               warp
-version:            3.4.2
+version:            3.4.3
 license:            MIT
 license-file:       LICENSE
 maintainer:         michael@snoyman.com
