diff --git a/warp/Network/Wai/Handler/Warp/Run.hs b/warp/Network/Wai/Handler/Warp/Run.hs index 0cde00d9..6c0696e9 100644 --- a/warp/Network/Wai/Handler/Warp/Run.hs +++ b/warp/Network/Wai/Handler/Warp/Run.hs @@ -13,7 +13,8 @@ import qualified Control.Exception 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.Conc (threadDelay) import GHC.IO.Exception (IOErrorType (..), IOException (..)) import Network.Socket ( SockAddr, @@ -300,18 +301,22 @@ acceptConnection set getConnMaker app counter ii = do fork set mkConn addr app counter ii acceptLoop - acceptNewConnection = do - ex <- UnliftIO.tryIO getConnMaker - 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 + acceptNewConnection = do + ex <- UnliftIO.tryIO getConnMaker + case ex of + Right x -> return $ Just x + Left e -> do + let getErrno (Errno cInt) = cInt + isErrno err = ioe_errno e == Just (getErrno err) + case () of + _ | isErrno eCONNABORTED -> acceptNewConnection + | isErrno eMFILE -> do + settingsOnException set Nothing $ toException e + threadDelay 100000 + 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).