@@ -328,15 +328,16 @@ Http2Stream::do_io_close(int /* flags */)
328328 // by the time this is called from transaction_done.
329329 closed = true ;
330330
331+ clear_timers ();
332+ clear_io_events ();
333+
334+ bool stream_deleted = false ;
331335 if (parent && this ->is_client_state_writeable ()) {
332336 // Make sure any trailing end of stream frames are sent
333337 // Wee will be removed at send_data_frames or closing connection phase
334- static_cast <Http2ClientSession *>(parent)->connection_state .send_data_frames (this );
338+ static_cast <Http2ClientSession *>(parent)->connection_state .send_data_frames (this , stream_deleted );
335339 }
336340
337- clear_timers ();
338- clear_io_events ();
339-
340341 // Wait until transaction_done is called from HttpSM to signal that the TXN_CLOSE hook has been executed
341342 }
342343}
@@ -517,8 +518,9 @@ Http2Stream::update_read_request(int64_t read_len, bool call_update, bool check_
517518void
518519Http2Stream::restart_sending ()
519520{
520- send_response_body ();
521- if (this ->write_vio .ntodo () > 0 && this ->write_vio .get_writer ()->write_avail () > 0 ) {
521+ bool stream_deleted;
522+ send_response_body (stream_deleted);
523+ if (!stream_deleted && this ->write_vio .ntodo () > 0 && this ->write_vio .get_writer ()->write_avail () > 0 ) {
522524 write_vio._cont ->handleEvent (VC_EVENT_WRITE_READY, &write_vio);
523525 }
524526}
@@ -569,6 +571,7 @@ Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t write_len,
569571 write_vio.nbytes , write_vio.ndone , write_vio.get_writer ()->write_avail (), bytes_avail);
570572
571573 if (bytes_avail > 0 || is_done) {
574+ bool stream_deleted;
572575 int send_event = (write_vio.ntodo () == bytes_avail || is_done) ? VC_EVENT_WRITE_COMPLETE : VC_EVENT_WRITE_READY;
573576
574577 // Process the new data
@@ -613,18 +616,20 @@ Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t write_len,
613616 // make sure to send the end of stream
614617 if (this ->response_is_data_available () || send_event == VC_EVENT_WRITE_COMPLETE) {
615618 if (send_event != VC_EVENT_WRITE_COMPLETE) {
616- send_response_body ();
617- // As with update_read_request, should be safe to call handler directly here if
618- // call_update is true. Commented out for now while tracking a performance regression
619- if (call_update) { // Coming from reenable. Safe to call the handler directly
620- if (write_vio._cont && this ->current_reader )
621- write_vio._cont ->handleEvent (send_event, &write_vio);
622- } else { // Called from do_io_write. Might still be setting up state. Send an event to let the dust settle
623- write_event = send_tracked_event (write_event, send_event, &write_vio);
619+ send_response_body (stream_deleted);
620+ if (!stream_deleted) {
621+ // As with update_read_request, should be safe to call handler directly here if
622+ // call_update is true. Commented out for now while tracking a performance regression
623+ if (call_update) { // Coming from reenable. Safe to call the handler directly
624+ if (write_vio._cont && this ->current_reader )
625+ write_vio._cont ->handleEvent (send_event, &write_vio);
626+ } else { // Called from do_io_write. Might still be setting up state. Send an event to let the dust settle
627+ write_event = send_tracked_event (write_event, send_event, &write_vio);
628+ }
624629 }
625630 } else {
626631 this ->mark_body_done ();
627- send_response_body ();
632+ send_response_body (stream_deleted );
628633 }
629634 }
630635 break ;
@@ -640,15 +645,17 @@ Http2Stream::update_write_request(IOBufferReader *buf_reader, int64_t write_len,
640645 // Defer sending the write complete until the send_data_frame has sent it all
641646 // this_ethread()->schedule_imm(this, send_event, &write_vio);
642647 this ->mark_body_done ();
643- send_response_body ();
648+ send_response_body (stream_deleted );
644649 retval = false ;
645650 } else {
646- send_response_body ();
647- if (call_update) { // Coming from reenable. Safe to call the handler directly
648- if (write_vio._cont && this ->current_reader )
649- write_vio._cont ->handleEvent (send_event, &write_vio);
650- } else { // Called from do_io_write. Might still be setting up state. Send an event to let the dust settle
651- write_event = send_tracked_event (write_event, send_event, &write_vio);
651+ send_response_body (stream_deleted);
652+ if (!stream_deleted) {
653+ if (call_update) { // Coming from reenable. Safe to call the handler directly
654+ if (write_vio._cont && this ->current_reader )
655+ write_vio._cont ->handleEvent (send_event, &write_vio);
656+ } else { // Called from do_io_write. Might still be setting up state. Send an event to let the dust settle
657+ write_event = send_tracked_event (write_event, send_event, &write_vio);
658+ }
652659 }
653660 }
654661 }
@@ -667,18 +674,20 @@ Http2Stream::push_promise(URL &url, const MIMEField *accept_encoding)
667674}
668675
669676void
670- Http2Stream::send_response_body ()
677+ Http2Stream::send_response_body (bool &stream_deleted )
671678{
679+ stream_deleted = false ;
672680 Http2ClientSession *parent = static_cast <Http2ClientSession *>(this ->get_parent ());
673681
682+ inactive_timeout_at = Thread::get_hrtime () + inactive_timeout;
683+
674684 if (Http2::stream_priority_enabled) {
675685 SCOPED_MUTEX_LOCK (lock, parent->connection_state .mutex , this_ethread ());
676686 parent->connection_state .schedule_stream (this );
677687 } else {
678688 SCOPED_MUTEX_LOCK (lock, parent->connection_state .mutex , this_ethread ());
679- parent->connection_state .send_data_frames (this );
689+ parent->connection_state .send_data_frames (this , stream_deleted );
680690 }
681- inactive_timeout_at = Thread::get_hrtime () + inactive_timeout;
682691}
683692
684693void
0 commit comments