Fix bug that transfer stuck when stream marked as top is deferred

This commit is contained in:
Tatsuhiro Tsujikawa 2014-04-03 15:48:19 +09:00
parent b671375abc
commit ac2a8ef4a2
4 changed files with 48 additions and 9 deletions

View File

@ -1708,8 +1708,14 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
next_readmax = nghttp2_session_next_data_read(session, stream);
if(next_readmax == 0) {
nghttp2_stream_defer_data(stream,
NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
rv = nghttp2_stream_defer_data(stream,
NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL,
&session->ob_pq);
if(nghttp2_is_fatal(rv)) {
return rv;
}
session->aob.item = NULL;
nghttp2_active_outbound_item_reset(&session->aob);
return NGHTTP2_ERR_DEFERRED;
@ -1719,7 +1725,13 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
next_readmax,
data_frame);
if(framerv == NGHTTP2_ERR_DEFERRED) {
nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER);
rv = nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER,
&session->ob_pq);
if(nghttp2_is_fatal(rv)) {
return rv;
}
session->aob.item = NULL;
nghttp2_active_outbound_item_reset(&session->aob);
return NGHTTP2_ERR_DEFERRED;
@ -2107,8 +2119,13 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
next_readmax = nghttp2_session_next_data_read(session, stream);
if(next_readmax == 0) {
nghttp2_stream_defer_data(stream,
NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
rv = nghttp2_stream_defer_data
(stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL, &session->ob_pq);
if(nghttp2_is_fatal(rv)) {
return rv;
}
aob->item = NULL;
nghttp2_active_outbound_item_reset(aob);
@ -2123,7 +2140,14 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
return rv;
}
if(rv == NGHTTP2_ERR_DEFERRED) {
nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER);
rv = nghttp2_stream_defer_data(stream,
NGHTTP2_STREAM_FLAG_DEFERRED_USER,
&session->ob_pq);
if(nghttp2_is_fatal(rv)) {
return rv;
}
aob->item = NULL;
nghttp2_active_outbound_item_reset(aob);

View File

@ -359,11 +359,17 @@ int nghttp2_stream_detach_data(nghttp2_stream *stream, nghttp2_pq *pq)
return stream_update_dep_on_detach_data(stream, pq);
}
void nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags)
int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags,
nghttp2_pq *pq)
{
assert(stream->data_item);
DEBUGF(fprintf(stderr, "stream: stream=%d defer data=%p cause=%02x\n",
stream->stream_id, stream->data_item, flags));
stream->flags |= flags;
return stream_update_dep_on_detach_data(stream, pq);
}
int nghttp2_stream_resume_deferred_data(nghttp2_stream *stream,

View File

@ -185,8 +185,15 @@ void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag);
* bitwise OR of zero or more of NGHTTP2_STREAM_FLAG_DEFERRED_USER and
* NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL. The |flags| indicates
* the reason of this action.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory
*/
void nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags);
int nghttp2_stream_defer_data(nghttp2_stream *stream, uint8_t flags,
nghttp2_pq *pq);
/*
* Detaches deferred data in this stream and it is back to active

View File

@ -2201,7 +2201,9 @@ void test_nghttp2_session_on_window_update_received(void)
CU_ASSERT(1 == user_data.frame_recv_cb_called);
CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE+16*1024 == stream->remote_window_size);
nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
CU_ASSERT(0 == nghttp2_stream_defer_data
(stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL,
&session->ob_pq));
CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
CU_ASSERT(2 == user_data.frame_recv_cb_called);