on master help sign in
Add an optional graceful shutdown timeout
aebd8d4Reid Draper
warp/Network/Wai/Handler/Warp.hs+13
@@ -70,12 +70,14 @@ module Network.Wai.Handler.Warp (
70 , setSlowlorisSize
70 , setSlowlorisSize
71 , setHTTP2Disabled
71 , setHTTP2Disabled
72 , setLogger
72 , setLogger
73+ , setGracefulShutdownTimeout
73 -- ** Getters
74 -- ** Getters
74 , getPort
75 , getPort
75 , getHost
76 , getHost
76 , getOnOpen
77 , getOnOpen
77 , getOnClose
78 , getOnClose
78 , getOnException
79 , getOnException
80+ , getGracefulShutdownTimeout
79 -- ** Exception handler
81 -- ** Exception handler
80 , defaultOnException
82 , defaultOnException
81 , defaultShouldDisplayException
83 , defaultShouldDisplayException
@@ -244,6 +246,10 @@ getOnClose = settingsOnClose
244getOnException :: Settings -> Maybe Request -> SomeException -> IO ()
246getOnException :: Settings -> Maybe Request -> SomeException -> IO ()
245getOnException = settingsOnException
247getOnException = settingsOnException
246
248
249+-- | Get the graceful shutdown timeout
250+getGracefulShutdownTimeout :: Settings -> Maybe Int
251+getGracefulShutdownTimeout = settingsGracefulShutdownTimeout
252+
247-- | A code to install shutdown handler.
253-- | A code to install shutdown handler.
248--
254--
249-- For instance, this code should set up a UNIX signal
255-- For instance, this code should set up a UNIX signal
@@ -347,6 +353,13 @@ setLogger :: (Request -> H.Status -> Maybe Integer -> IO ())
347 -> Settings -> Settings
353 -> Settings -> Settings
348setLogger lgr y = y { settingsLogger = lgr }
354setLogger lgr y = y { settingsLogger = lgr }
349
355
356+-- | Set the graceful shutdown timeout. A timeout of `Nothing' will
357+-- wait indefinitely, and a number, if provided, will be treated as seconds
358+-- to wait for requests to finish, before shutting down the server entirely.
359+setGracefulShutdownTimeout :: Maybe Int
360+ -> Settings -> Settings
361+setGracefulShutdownTimeout time y = y { settingsGracefulShutdownTimeout = time }
362+
350-- | Explicitly pause the slowloris timeout.
363-- | Explicitly pause the slowloris timeout.
351--
364--
352-- This is useful for cases where you partially consume a request body. For
365-- This is useful for cases where you partially consume a request body. For
warp/Network/Wai/Handler/Warp/Run.hs+10−3
@@ -45,6 +45,7 @@ import qualified Network.Wai.Handler.Warp.Timeout as T
45import Network.Wai.Handler.Warp.Types
45import Network.Wai.Handler.Warp.Types
46import Network.Wai.Internal (ResponseReceived (ResponseReceived))
46import Network.Wai.Internal (ResponseReceived (ResponseReceived))
47import System.Environment (getEnvironment)
47import System.Environment (getEnvironment)
48+import System.Timeout (timeout)
48
49
49#if WINDOWS
50#if WINDOWS
50import Network.Wai.Handler.Warp.Windows
51import Network.Wai.Handler.Warp.Windows
@@ -218,7 +219,7 @@ acceptConnection set getConnMaker app counter ii0 = do
218 -- ensure that no async exception is throw between the call to
219 -- ensure that no async exception is throw between the call to
219 -- acceptNewConnection and the registering of connClose.
220 -- acceptNewConnection and the registering of connClose.
220 void $ mask_ acceptLoop
221 void $ mask_ acceptLoop
221− gracefulShutdown counter
222+ gracefulShutdown set counter
222 where
223 where
223 acceptLoop = do
224 acceptLoop = do
224 -- Allow async exceptions before receiving the next connection maker.
225 -- Allow async exceptions before receiving the next connection maker.
@@ -495,5 +496,11 @@ setSocketCloseOnExec _ = return ()
495setSocketCloseOnExec socket = F.setFileCloseOnExec $ fromIntegral $ fdSocket socket
496setSocketCloseOnExec socket = F.setFileCloseOnExec $ fromIntegral $ fdSocket socket
496#endif
497#endif
497
498
498−gracefulShutdown :: Counter -> IO ()
499+gracefulShutdown :: Settings -> Counter -> IO ()
499−gracefulShutdown counter = waitForZero counter
500+gracefulShutdown set counter =
501+ case settingsGracefulShutdownTimeout set of
502+ Nothing ->
503+ waitForZero counter
504+ (Just seconds) ->
505+ void (timeout (seconds * microsPerSecond) (waitForZero counter))
506+ where microsPerSecond = 1000000
warp/Network/Wai/Handler/Warp/Settings.hs+4
@@ -101,6 +101,9 @@ data Settings = Settings
101 -- ^ A log function. Default: no action.
101 -- ^ A log function. Default: no action.
102 --
102 --
103 -- Since 3.X.X.
103 -- Since 3.X.X.
104+ , settingsGracefulShutdownTimeout :: Maybe Int
105+ -- ^ An optional timeout to limit the time (in seconds) waiting for
106+ -- a graceful shutdown of the web server.
104 }
107 }
105
108
106-- | Specify usage of the PROXY protocol.
109-- | Specify usage of the PROXY protocol.
@@ -135,6 +138,7 @@ defaultSettings = Settings
135 , settingsSlowlorisSize = 2048
138 , settingsSlowlorisSize = 2048
136 , settingsHTTP2Enabled = True
139 , settingsHTTP2Enabled = True
137 , settingsLogger = \_ _ _ -> return ()
140 , settingsLogger = \_ _ _ -> return ()
141+ , settingsGracefulShutdownTimeout = Nothing
138 }
142 }
139
143
140-- | Apply the logic provided by 'defaultOnException' to determine if an
144-- | Apply the logic provided by 'defaultOnException' to determine if an