nghttp: move ContinueTimer start to on_frame_send

The ContinueTimer could expire before the full HEADERS frame was
actually sent. By moving the call to timer->start() to the
on_frame_send_callback(), this race is fixed.
This commit is contained in:
Jacob Champion 2016-03-28 15:24:20 -07:00
parent 3b7b6a660e
commit edb874e659
1 changed files with 32 additions and 4 deletions

View File

@ -484,7 +484,6 @@ int submit_request(HttpClient *client, const Headers &headers, Request *req) {
if (expect_continue) { if (expect_continue) {
auto timer = std::make_shared<ContinueTimer>(client->loop, req); auto timer = std::make_shared<ContinueTimer>(client->loop, req);
timer->start();
req->continue_timer = timer; req->continue_timer = timer;
client->continue_timers.push_back(timer); client->continue_timers.push_back(timer);
@ -1983,6 +1982,35 @@ int before_frame_send_callback(nghttp2_session *session,
} // namespace } // namespace
namespace {
int on_frame_send_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data) {
if (config.verbose) {
verbose_on_frame_send_callback(session, frame, user_data);
}
if (frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
return 0;
}
auto req = static_cast<Request *>(
nghttp2_session_get_stream_user_data(session, frame->hd.stream_id));
if (!req) {
return 0;
}
// If this request is using Expect/Continue, start its ContinueTimer.
std::shared_ptr<ContinueTimer> timer = req->continue_timer.lock();
if (timer) {
timer->start();
}
return 0;
}
} // namespace
namespace { namespace {
int on_frame_not_send_callback(nghttp2_session *session, int on_frame_not_send_callback(nghttp2_session *session,
const nghttp2_frame *frame, int lib_error_code, const nghttp2_frame *frame, int lib_error_code,
@ -2342,9 +2370,6 @@ int run(char **uris, int n) {
on_frame_recv_callback2); on_frame_recv_callback2);
if (config.verbose) { if (config.verbose) {
nghttp2_session_callbacks_set_on_frame_send_callback(
callbacks, verbose_on_frame_send_callback);
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback( nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
callbacks, verbose_on_invalid_frame_recv_callback); callbacks, verbose_on_invalid_frame_recv_callback);
@ -2364,6 +2389,9 @@ int run(char **uris, int n) {
nghttp2_session_callbacks_set_before_frame_send_callback( nghttp2_session_callbacks_set_before_frame_send_callback(
callbacks, before_frame_send_callback); callbacks, before_frame_send_callback);
nghttp2_session_callbacks_set_on_frame_send_callback(
callbacks, on_frame_send_callback);
nghttp2_session_callbacks_set_on_frame_not_send_callback( nghttp2_session_callbacks_set_on_frame_not_send_callback(
callbacks, on_frame_not_send_callback); callbacks, on_frame_not_send_callback);