@@ -536,7 +536,7 @@ void windows_request_context::async_process_request(HTTP_REQUEST_ID request_id,
536536 {
537537 CancelThreadpoolIo (pServer->m_threadpool_io );
538538 m_msg.reply (status_codes::InternalError);
539- do_response ( true );
539+ init_response_callbacks (DontWaitForBody );
540540 }
541541}
542542
@@ -548,7 +548,7 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD
548548 if (error_code != NO_ERROR)
549549 {
550550 m_msg.reply (status_codes::InternalError);
551- do_response ( true );
551+ init_response_callbacks (DontWaitForBody );
552552 }
553553 else
554554 {
@@ -582,7 +582,9 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD
582582 else
583583 {
584584 m_msg.reply (status_codes::BadRequest, badRequestMsg);
585- do_response (true );
585+
586+ // Even though we have a bad request, we should wait for the body otherwise we risk racing over m_overlapped
587+ init_response_callbacks (WaitForBody);
586588 }
587589 }
588590}
@@ -623,7 +625,6 @@ void windows_request_context::read_request_body_chunk()
623625 else
624626 {
625627 m_msg._get_impl ()->_complete (0 , std::make_exception_ptr (http_exception (error_code)));
626- m_msg._reply_if_not_already (status_codes::InternalError);
627628 }
628629 }
629630}
@@ -649,7 +650,6 @@ void windows_request_context::read_body_io_completion(DWORD error_code, DWORD by
649650 {
650651 request_body_buf.commit (0 );
651652 m_msg._get_impl ()->_complete (0 , std::make_exception_ptr (http_exception (error_code)));
652- m_msg._reply_if_not_already (status_codes::InternalError);
653653 }
654654}
655655
@@ -660,7 +660,7 @@ void windows_request_context::dispatch_request_to_listener(_In_ web::http::exper
660660 // Save http_request copy to dispatch to user's handler in case content_ready() completes before.
661661 http_request request = m_msg;
662662
663- do_response ( false );
663+ init_response_callbacks (WaitForBody );
664664
665665 // Look up the lock for the http_listener.
666666 auto *pServer = static_cast <http_windows_server *>(http_server_api::server_api ());
@@ -693,7 +693,7 @@ void windows_request_context::dispatch_request_to_listener(_In_ web::http::exper
693693 }
694694}
695695
696- void windows_request_context::do_response ( bool bad_request )
696+ void windows_request_context::init_response_callbacks (ShouldWaitForBody shouldWait )
697697{
698698 // Use a proxy event so we're not causing a circular reference between the http_request and the response task
699699 pplx::task_completion_event<void > proxy_content_ready;
@@ -722,7 +722,7 @@ void windows_request_context::do_response(bool bad_request)
722722 proxy_content_ready.set ();
723723 });
724724
725- get_response_task.then ([this , bad_request, proxy_content_ready](pplx::task<http::http_response> responseTask)
725+ get_response_task.then ([this , proxy_content_ready](pplx::task<http::http_response> responseTask)
726726 {
727727 // Don't let an exception from sending the response bring down the server.
728728 try
@@ -741,19 +741,25 @@ void windows_request_context::do_response(bool bad_request)
741741 m_response = http::http_response (status_codes::InternalError);
742742 }
743743
744- if (bad_request)
745- {
746- async_process_response ();
747- }
748- else
744+ // Wait until the content download finished before replying because m_overlapped is reused,
745+ // and we don't want to delete 'this' if the body is still downloading
746+ pplx::create_task (proxy_content_ready).then ([this ](pplx::task<void > t)
749747 {
750- // Wait until the content download finished before replying.
751- pplx::create_task (proxy_content_ready).then ([this ](pplx::task<void > requestBody)
748+ try
752749 {
750+ t.wait ();
753751 async_process_response ();
754- });
755- }
752+ }
753+ catch (...)
754+ {
755+ }
756+ }).wait ();
756757 });
758+
759+ if (shouldWait == DontWaitForBody)
760+ {
761+ proxy_content_ready.set ();
762+ }
757763}
758764
759765void windows_request_context::async_process_response ()
0 commit comments