@@ -17,7 +17,7 @@ import qualified Control.Concurrent as Conc (yield)
17import Control.Exception as E
17import Control.Exception as E
18import qualified Data.ByteString as S
18import qualified Data.ByteString as S
19import Data.Char (chr)
19import Data.Char (chr)
20−import Data.IORef (IORef, newIORef, readIORef, writeIORef, atomicModifyIORef')
20+import Data.IORef (IORef, newIORef, readIORef, writeIORef)
21import Data.Streaming.Network (bindPortTCP)
21import Data.Streaming.Network (bindPortTCP)
22import Foreign.C.Error (Errno(..), eCONNABORTED)
22import Foreign.C.Error (Errno(..), eCONNABORTED)
23import GHC.IO.Exception (IOException(..))
23import GHC.IO.Exception (IOException(..))
@@ -59,7 +59,11 @@ import Network.Socket (fdSocket)
60-- | Creating 'Connection' for plain HTTP based on a given socket.
60-- | Creating 'Connection' for plain HTTP based on a given socket.
61socketConnection :: Settings -> Socket -> IO Connection
61socketConnection :: Settings -> Socket -> IO Connection
62+#if MIN_VERSION_network(3,1,1)
62socketConnection set s = do
63socketConnection set s = do
65+socketConnection _ s = do
63 bufferPool <- newBufferPool
67 bufferPool <- newBufferPool
64 writeBuf <- allocateBuffer bufferSize
68 writeBuf <- allocateBuffer bufferSize
65 let sendall = Sock.sendAll s
69 let sendall = Sock.sendAll s
@@ -76,7 +80,7 @@ socketConnection set s = do
76 if tm == 0 then
80 if tm == 0 then
79− gracefulClose s tm
83+ gracefulClose s tm `E.catch` \(E.SomeException _) -> return ()
81 , connClose = close s
85 , connClose = close s
@@ -282,10 +286,7 @@ fork :: Settings
282fork set mkConn addr app counter ii = settingsFork set $ \unmask ->
286fork set mkConn addr app counter ii = settingsFork set $ \unmask ->
283 -- Call the user-supplied on exception code if any
287 -- Call the user-supplied on exception code if any
284 -- exceptions are thrown.
288 -- exceptions are thrown.
285− handle (settingsOnException set Nothing) .
289+ handle (settingsOnException set Nothing) $
286− -- Allocate a new IORef indicating whether the connection has been
287− -- closed, to avoid double-freeing a connection
288− withClosedRef $ \ref ->
289 -- Run the connection maker to get a new connection, and ensure
290 -- Run the connection maker to get a new connection, and ensure
290 -- that the connection is closed. If the mkConn call throws an
291 -- that the connection is closed. If the mkConn call throws an
291 -- exception, we will leak the connection. If the mkConn call is
292 -- exception, we will leak the connection. If the mkConn call is
@@ -296,21 +297,13 @@ fork set mkConn addr app counter ii = settingsFork set $ \unmask ->
296 -- We grab the connection before registering timeouts since the
297 -- We grab the connection before registering timeouts since the
297 -- timeouts will be useless during connection creation, due to the
298 -- timeouts will be useless during connection creation, due to the
298 -- fact that async exceptions are still masked.
299 -- fact that async exceptions are still masked.
299− bracket mkConn (cleanUp ref) (serve unmask ref)
300+ bracket mkConn cleanUp (serve unmask)
301− withClosedRef inner = newIORef False >>= inner
303− closeConn ref conn = do
304− isClosed <- atomicModifyIORef' ref $ \x -> (True, x)
305− unless isClosed $ connClose conn
307− cleanUp ref (conn, _) = closeConn ref conn `finally` connFree conn
302+ cleanUp (conn, _) = connClose conn `finally` connFree conn
309 -- We need to register a timeout handler for this thread, and
304 -- We need to register a timeout handler for this thread, and
310− -- cancel that handler as soon as we exit. We additionally close
305+ -- cancel that handler as soon as we exit.
311− -- the connection immediately in case the child thread catches the
312− -- async exception or performs some long-running cleanup action.
313− serve unmask ref (conn, transport) = bracket register cancel $ \th -> do
306+ serve unmask (conn, transport) = bracket register cancel $ \th -> do
314 -- We now have fully registered a connection close handler in
307 -- We now have fully registered a connection close handler in
315 -- the case of all exceptions, so it is safe to once again
308 -- the case of all exceptions, so it is safe to once again
316 -- allow async exceptions.
309 -- allow async exceptions.
@@ -322,8 +315,7 @@ fork set mkConn addr app counter ii = settingsFork set $ \unmask ->
322 -- above ensures the connection is closed.
315 -- above ensures the connection is closed.
323 when goingon $ serveConnection conn ii th addr transport set app
316 when goingon $ serveConnection conn ii th addr transport set app
325− register = T.registerKillThread (timeoutManager ii)
318+ register = T.registerKillThread (timeoutManager ii) (connClose conn)
326− (closeConn ref conn)
327 cancel = T.cancel
319 cancel = T.cancel
329 onOpen adr = increase counter >> settingsOnOpen set adr
321 onOpen adr = increase counter >> settingsOnOpen set adr
@@ -350,11 +342,19 @@ serveConnection conn ii th origAddr transport settings app = do
350 istatus <- newIORef False
342 istatus <- newIORef False
351 if settingsHTTP2Enabled settings && h2 then do
343 if settingsHTTP2Enabled settings && h2 then do
352 rawRecvN <- makeReceiveN bs (connRecv conn) (connRecvBuf conn)
344 rawRecvN <- makeReceiveN bs (connRecv conn) (connRecvBuf conn)
345+ -- This thread becomes the sender in http2 library.
346+ -- In the case of event source, one request comes and one
347+ -- worker gets busy. But it is likely that the receiver does
348+ -- not receive any data at all while the sender is sending
349+ -- output data from the worker. It's not good enough to tickle
350+ -- the time handler in the receiver only. So, we should tickle
351+ -- the time handler in both the receiver and the sender.
353 let recvN = wrappedRecvN th istatus (settingsSlowlorisSize settings) rawRecvN
352 let recvN = wrappedRecvN th istatus (settingsSlowlorisSize settings) rawRecvN
353+ sendBS x = connSendAll conn x >> T.tickle th
354 -- fixme: origAddr
354 -- fixme: origAddr
356 setConnHTTP2 conn True
356 setConnHTTP2 conn True
357− http2 conn transport ii origAddr settings recvN app
357+ http2 conn transport ii origAddr settings recvN sendBS app
359 src <- mkSource (wrappedRecv conn th istatus (settingsSlowlorisSize settings))
359 src <- mkSource (wrappedRecv conn th istatus (settingsSlowlorisSize settings))
360 writeIORef istatus True
360 writeIORef istatus True