on master help sign in
HTTP/2 GOAWAY are not delivered to clients sometime because close(2)

is called immediately. This is reported in #673. We can reproduce this with h2spec: % h2spec http2/5.4 http2/7 5. Streams and Multiplexing 5.4. Error Handling 5.4.1. Connection Error Handling × 1: Sends an invalid PING frame for connection close -> The endpoint MUST close the TCP connection Expected: Connection closed Actual: Error: read tcp 127.0.0.1:56529->127.0.0.1:80: read: connection reset by peer 7. Error Codes × 1: Sends a GOAWAY frame with unknown error code -> The endpoint MUST NOT trigger any special behavior. Expected: Connection closed PING Frame (length:8, flags:0x01, stream_id:0, opaque_data:h2spec) Actual: Error: read tcp 127.0.0.1:56578->127.0.0.1:80: read: connection reset by peer To fix this, we use "gracefulClose" in the network library.

commitaee7377197a30aff4cdff3064a569bdf01d1d42b authorKazu Yamamoto <kazu@iij.ad.jp> dateWed 10 Jul 2019, 11:29 (7 years ago) parent209b133
2 files changed+14
warp-tls/Network/Wai/Handler/WarpTLS.hs+7 warp/Network/Wai/Handler/Warp/Run.hs+7
warp-tls/Network/Wai/Handler/WarpTLS.hs+7
@@ -53,6 +53,9 @@ import qualified Data.IORef as I
5353import Data.Streaming.Network (bindPortTCP, safeRecv)
5454import Data.Typeable (Typeable)
5555import Network.Socket (Socket, close, withSocketsDo, SockAddr, accept)
56+#if MIN_VERSION_network(3,1,1)
57+import Network.Socket (gracefulClose)
58+#endif
5659import Network.Socket.ByteString (sendAll)
5760import qualified Network.TLS as TLS
5861import qualified Crypto.PubKey.DH as DH
@@ -355,7 +358,11 @@ httpOverTls TLSSettings{..} s bs0 params = do
355358 where
356359 backend recvN = TLS.Backend {
357360 TLS.backendFlush = return ()
361+#if MIN_VERSION_network(3,1,1)
362+ , TLS.backendClose = gracefulClose s 5000
363+#else
358364 , TLS.backendClose = close s
365+#endif
359366 , TLS.backendSend = sendAll' s
360367 , TLS.backendRecv = recvN
361368 }
warp/Network/Wai/Handler/Warp/Run.hs+7
@@ -23,6 +23,9 @@ import Foreign.C.Error (Errno(..), eCONNABORTED)
2323import GHC.IO.Exception (IOException(..))
2424import qualified Network.HTTP2 as H2
2525import Network.Socket (Socket, close, accept, withSocketsDo, SockAddr(SockAddrInet, SockAddrInet6), setSocketOption, SocketOption(..))
26+#if MIN_VERSION_network(3,1,1)
27+import Network.Socket (gracefulClose)
28+#endif
2629import qualified Network.Socket.ByteString as Sock
2730import Network.Wai
2831import Network.Wai.Internal (ResponseReceived (ResponseReceived))
@@ -64,7 +67,11 @@ socketConnection s = do
6467 connSendMany = Sock.sendMany s
6568 , connSendAll = sendall
6669 , connSendFile = sendFile s writeBuf bufferSize sendall
70+#if MIN_VERSION_network(3,1,1)
71+ , connClose = gracefulClose s 5000
72+#else
6773 , connClose = close s
74+#endif
6875 , connFree = freeBuffer writeBuf
6976 , connRecv = receive s bufferPool
7077 , connRecvBuf = receiveBuf s