on master help sign in
moving comments and mask_.
f01c4aeKazu Yamamoto
warp/Network/Wai/Handler/Warp/Run.hs+17−18
@@ -123,26 +123,10 @@ runSettingsConnectionMakerSecure :: Settings -> IO (IO (Connection, Bool), SockA
123runSettingsConnectionMakerSecure set getConnMaker app = do
123runSettingsConnectionMakerSecure set getConnMaker app = do
124 settingsBeforeMainLoop set
124 settingsBeforeMainLoop set
125
125
126− -- Note that there is a thorough discussion of the exception safety of the
127− -- following code at: https://github.com/yesodweb/wai/issues/146
128− --
129− -- We need to make sure of two things:
130− --
131− -- 1. Asynchronous exceptions are not blocked entirely in the main loop.
132− -- Doing so would make it impossible to kill the Warp thread.
133− --
134− -- 2. Once a connection maker is received via getConnLoop, the connection
135− -- is guaranteed to be closed, even in the presence of async exceptions.
136− --
137− -- Our approach is explained in the comments below.
138−
139− -- First mask all exceptions in the main loop. This is necessary to ensure
140− -- that no async exception is throw between the call to getConnLoop and the
141− -- registering of connClose.
142 D.withDateCache $ \dc ->
126 D.withDateCache $ \dc ->
143 F.withFdCache fdCacheDurationInSeconds $ \fc ->
127 F.withFdCache fdCacheDurationInSeconds $ \fc ->
144 withTimeoutManager $ \tm ->
128 withTimeoutManager $ \tm ->
145− mask_ $ acceptConnection set getConnMaker app dc fc tm
129+ acceptConnection set getConnMaker app dc fc tm
146 where
130 where
147 fdCacheDurationInSeconds = settingsFdCacheDuration set * 1000000
131 fdCacheDurationInSeconds = settingsFdCacheDuration set * 1000000
148 withTimeoutManager f =
132 withTimeoutManager f =
@@ -153,6 +137,18 @@ runSettingsConnectionMakerSecure set getConnMaker app = do
153 f
137 f
154 Just tm -> f tm
138 Just tm -> f tm
155
139
140+-- Note that there is a thorough discussion of the exception safety of the
141+-- following code at: https://github.com/yesodweb/wai/issues/146
142+--
143+-- We need to make sure of two things:
144+--
145+-- 1. Asynchronous exceptions are not blocked entirely in the main loop.
146+-- Doing so would make it impossible to kill the Warp thread.
147+--
148+-- 2. Once a connection maker is received via getConnLoop, the connection
149+-- is guaranteed to be closed, even in the presence of async exceptions.
150+--
151+-- Our approach is explained in the comments below.
156acceptConnection :: Settings
152acceptConnection :: Settings
157 -> IO (IO (Connection, Bool), SockAddr)
153 -> IO (IO (Connection, Bool), SockAddr)
158 -> Application
154 -> Application
@@ -160,7 +156,10 @@ acceptConnection :: Settings
160 -> Maybe F.MutableFdCache
156 -> Maybe F.MutableFdCache
161 -> T.Manager
157 -> T.Manager
162 -> IO ()
158 -> IO ()
159+-- First mask all exceptions in the main loop. This is necessary to ensure
160+-- that no async exception is throw between the call to getConnLoop and the
161+-- registering of connClose.
163−acceptConnection set getConnMaker app dc fc tm = do
162+acceptConnection set getConnMaker app dc fc tm = mask_ $ do
164 -- Allow async exceptions before receiving the next connection maker.
163 -- Allow async exceptions before receiving the next connection maker.
165 allowInterrupt
164 allowInterrupt
166
165