-
-
Notifications
You must be signed in to change notification settings - Fork 6.7k
HTTP/2: curl hangs with upload if server sends response early and resets stream #986
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I attempted to fix this. The following patch seems to work, but I have not checked side effects. diff --git a/lib/http.h b/lib/http.h
index 6529005..9fb669c 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -168,6 +168,7 @@ struct HTTP {
const uint8_t *pausedata; /* pointer to data received in on_data_chunk */
size_t pauselen; /* the number of bytes left in data */
bool closed; /* TRUE on HTTP2 stream close */
+ bool close_handled; /* TRUE if stream closure is handled by libcurl */
uint32_t error_code; /* HTTP/2 error code */
char *mem; /* points to a buffer in memory to store received data */
diff --git a/lib/http2.c b/lib/http2.c
index a14f75e..e611058 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -151,6 +151,7 @@ void Curl_http2_setup_req(struct Curl_easy *data)
http->pauselen = 0;
http->error_code = NGHTTP2_NO_ERROR;
http->closed = FALSE;
+ http->close_handled = FALSE;
http->mem = data->state.buffer;
http->len = BUFSIZE;
http->memlen = 0;
@@ -1216,6 +1217,8 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
}
}
+ stream->close_handled = TRUE;
+
DEBUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
return 0;
}
@@ -1520,6 +1523,14 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
DEBUGF(infof(conn->data, "http2_send len=%zu\n", len));
if(stream->stream_id != -1) {
+ if(stream->close_handled) {
+ infof(conn->data, "stream %d closed\n", stream->stream_id);
+ *err = CURLE_HTTP2;
+ return -1;
+ }
+ else if(stream->closed) {
+ return http2_handle_stream_close(conn, conn->data, stream, err);
+ }
/* If stream_id != -1, we have dispatched request HEADERS, and now
are going to send or sending request body in DATA frame */
stream->upload_mem = mem; Here, we use error code CURLE_HTTP2. Not sure it is the best code in this situation. |
Thanks, I'll give this a closer look and test out a little before I merge. Regarding the error code, I think it is time for us to go through and check if we shouldn't add a few more error codes for h2 specific situations that would be helpful if we exposed better to users instead of shoveling everything under a generic "http2 error" code. |
There is a new error code we added CURLE_HTTP2_STREAM a while ago, but I know you are aware of this, does it not apply? |
Oh right. forgot about that one. Yes it seems suitable for this case. Thanks, will fix! |
I did this
Run h2 server. With --early-response option, this server returns HTTP response without waiting for upload completion. Additionally, it sends RST_STREAM if it expects request body from client:
Then do some large upload from curl:
And it stuck.
Background info: nghttp2/nghttp2#669
I expected the following
curl should detect stream closure, and exit. Since upload was not completed, with some error code (not sure which one we should use here).
curl/libcurl version
I build curl from git master
operating system
Linux
The text was updated successfully, but these errors were encountered: