Skip to content

Commit

Permalink
HTTP/2 GOAWAY are not delivered to clients sometime because close(2)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
kazu-yamamoto committed Sep 10, 2019
1 parent 209b133 commit aee7377
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 0 deletions.
7 changes: 7 additions & 0 deletions warp-tls/Network/Wai/Handler/WarpTLS.hs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ import qualified Data.IORef as I
import Data.Streaming.Network (bindPortTCP, safeRecv)
import Data.Typeable (Typeable)
import Network.Socket (Socket, close, withSocketsDo, SockAddr, accept)
#if MIN_VERSION_network(3,1,1)
import Network.Socket (gracefulClose)
#endif
import Network.Socket.ByteString (sendAll)
import qualified Network.TLS as TLS
import qualified Crypto.PubKey.DH as DH
Expand Down Expand Up @@ -355,7 +358,11 @@ httpOverTls TLSSettings{..} s bs0 params = do
where
backend recvN = TLS.Backend {
TLS.backendFlush = return ()
#if MIN_VERSION_network(3,1,1)
, TLS.backendClose = gracefulClose s 5000
#else
, TLS.backendClose = close s
#endif
, TLS.backendSend = sendAll' s
, TLS.backendRecv = recvN
}
Expand Down
7 changes: 7 additions & 0 deletions warp/Network/Wai/Handler/Warp/Run.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import Foreign.C.Error (Errno(..), eCONNABORTED)
import GHC.IO.Exception (IOException(..))
import qualified Network.HTTP2 as H2
import Network.Socket (Socket, close, accept, withSocketsDo, SockAddr(SockAddrInet, SockAddrInet6), setSocketOption, SocketOption(..))
#if MIN_VERSION_network(3,1,1)
import Network.Socket (gracefulClose)
#endif
import qualified Network.Socket.ByteString as Sock
import Network.Wai
import Network.Wai.Internal (ResponseReceived (ResponseReceived))
Expand Down Expand Up @@ -64,7 +67,11 @@ socketConnection s = do
connSendMany = Sock.sendMany s
, connSendAll = sendall
, connSendFile = sendFile s writeBuf bufferSize sendall
#if MIN_VERSION_network(3,1,1)
, connClose = gracefulClose s 5000
#else
, connClose = close s
#endif
, connFree = freeBuffer writeBuf
, connRecv = receive s bufferPool
, connRecvBuf = receiveBuf s
Expand Down

0 comments on commit aee7377

Please sign in to comment.