diff options
author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2014-02-27 01:21:17 +0900 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2014-02-28 23:28:39 +0100 |
commit | cde0cf7c5ede69c68cb00cba3d1a6ccc27c24bc9 (patch) | |
tree | 1072828797a999c8d68a4e70ec65a9ec9d629bcf | |
parent | 53f1f4a18ee7e3ac5fbe44a0e16b33b27465432b (diff) |
Fix bug that HTTP/2 hangs if whole response body is read with headers
For HTTP/2, we may read up everything including responde body with
header fields in Curl_http_readwrite_headers. If no content-length is
provided, curl waits for the connection close, which we emulate it
using conn->proto.httpc.closed = TRUE. The thing is if we read
everything, then http2_recv won't be called and we cannot signal the
HTTP/2 stream has closed. As a workaround, we return nonzero from
data_pending to call http2_recv.
-rw-r--r-- | lib/http2.c | 4 | ||||
-rw-r--r-- | lib/transfer.c | 11 |
2 files changed, 14 insertions, 1 deletions
diff --git a/lib/http2.c b/lib/http2.c index d364f3a77..b20854a3b 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -514,6 +514,10 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, (void)sockindex; /* we always do HTTP2 on sockindex 0 */ + if(httpc->closed) { + return 0; + } + /* Nullify here because we call nghttp2_session_send() and they might refer to the old buffer. */ httpc->upload_mem = NULL; diff --git a/lib/transfer.c b/lib/transfer.c index 83727db68..8748c6a01 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -310,7 +310,16 @@ static int data_pending(const struct connectdata *conn) /* in the case of libssh2, we can never be really sure that we have emptied its internal buffers so we MUST always try until we get EAGAIN back */ return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) || - Curl_ssl_data_pending(conn, FIRSTSOCKET); + Curl_ssl_data_pending(conn, FIRSTSOCKET) || + /* For HTTP/2, we may read up everything including responde body + with header fields in Curl_http_readwrite_headers. If no + content-length is provided, curl waits for the connection + close, which we emulate it using conn->proto.httpc.closed = + TRUE. The thing is if we read everything, then http2_recv won't + be called and we cannot signal the HTTP/2 stream has closed. As + a workaround, we return nonzero here to call http2_recv. */ + ((conn->handler->protocol&CURLPROTO_HTTP) && conn->httpversion == 20 && + conn->proto.httpc.closed); } static void read_rewind(struct connectdata *conn, |