You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ma...@apache.org on 2018/08/08 07:55:17 UTC

[trafficserver] branch quic-latest updated: Erase "ack_only" lost packet correctly

This is an automated email from the ASF dual-hosted git repository.

masaori pushed a commit to branch quic-latest
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/quic-latest by this push:
     new fad804a  Erase "ack_only" lost packet correctly
fad804a is described below

commit fad804a84d1a45f7ac4f24baea0d5838e15476db
Author: Masaori Koshiba <ma...@apache.org>
AuthorDate: Wed Aug 8 16:48:51 2018 +0900

    Erase "ack_only" lost packet correctly
    
    To avoid heap-use-after-free caused by erasing elements in the loop
---
 iocore/net/quic/QUICLossDetector.cc | 48 ++++++++++++++++++++++++-------------
 iocore/net/quic/QUICLossDetector.h  |  3 +++
 2 files changed, 35 insertions(+), 16 deletions(-)

diff --git a/iocore/net/quic/QUICLossDetector.cc b/iocore/net/quic/QUICLossDetector.cc
index c6a5014..2773d80 100644
--- a/iocore/net/quic/QUICLossDetector.cc
+++ b/iocore/net/quic/QUICLossDetector.cc
@@ -427,36 +427,39 @@ QUICLossDetector::_detect_lost_packets(QUICPacketNumber largest_acked_packet_num
     delay_until_lost = 5.0 / 4.0 * std::max(this->_latest_rtt, this->_smoothed_rtt);
   }
 
-  for (auto &unacked : this->_sent_packets) {
-    if (unacked.first >= largest_acked_packet_number) {
+  for (auto it = this->_sent_packets.begin(); it != this->_sent_packets.end();) {
+    if (it->first >= largest_acked_packet_number) {
       break;
     }
-    ink_hrtime time_since_sent = Thread::get_hrtime() - unacked.second->time;
-    uint64_t delta             = largest_acked_packet_number - unacked.second->packet_number;
+    ink_hrtime time_since_sent = Thread::get_hrtime() - it->second->time;
+    uint64_t delta             = largest_acked_packet_number - it->second->packet_number;
     if (time_since_sent > delay_until_lost || delta > this->_reordering_threshold) {
       if (time_since_sent > delay_until_lost) {
         QUICLDDebug("Lost: time since sent is too long (PN=%" PRId64 " sent=%" PRId64 ", delay=%lf, fraction=%lf, lrtt=%" PRId64
                     ", srtt=%" PRId64 ")",
-                    unacked.first, time_since_sent, delay_until_lost, this->_time_reordering_fraction, this->_latest_rtt,
+                    it->first, time_since_sent, delay_until_lost, this->_time_reordering_fraction, this->_latest_rtt,
                     this->_smoothed_rtt);
       } else {
         QUICLDDebug("Lost: packet delta is too large (PN=%" PRId64 " largest=%" PRId64 " unacked=%" PRId64 " threshold=%" PRId32
                     ")",
-                    unacked.first, largest_acked_packet_number, unacked.second->packet_number, this->_reordering_threshold);
+                    it->first, largest_acked_packet_number, it->second->packet_number, this->_reordering_threshold);
       }
 
-      if (!unacked.second->ack_only) {
-        lost_packets.insert({unacked.first, unacked.second.get()});
+      if (!it->second->ack_only) {
+        lost_packets.insert({it->first, it->second.get()});
       } else {
         // -- ADDITIONAL CODE --
         // We remove only "ack-only" packets for life time management of packets.
         // Packets in lost_packets will be removed from sent_packet later.
-        this->_remove_from_sent_packet_list(unacked.first);
+        it = this->_remove_from_sent_packet_list(it);
+        continue;
         // -- END OF ADDITIONAL CODE --
       }
     } else if (this->_loss_time == 0 && delay_until_lost != INFINITY) {
       this->_loss_time = Thread::get_hrtime() + delay_until_lost - time_since_sent;
     }
+
+    ++it;
   }
 
   // Inform the congestion controller of lost packets and
@@ -582,21 +585,34 @@ QUICLossDetector::_remove_from_sent_packet_list(QUICPacketNumber packet_number)
 {
   SCOPED_MUTEX_LOCK(lock, this->_loss_detection_mutex, this_ethread());
 
-  // Decrement counters
   auto ite = this->_sent_packets.find(packet_number);
-  if (ite != this->_sent_packets.end()) {
-    if (ite->second->handshake) {
+  this->_decrement_outstanding_counters(ite);
+  this->_sent_packets.erase(packet_number);
+}
+
+std::map<QUICPacketNumber, PacketInfoUPtr>::iterator
+QUICLossDetector::_remove_from_sent_packet_list(std::map<QUICPacketNumber, PacketInfoUPtr>::iterator it)
+{
+  SCOPED_MUTEX_LOCK(lock, this->_loss_detection_mutex, this_ethread());
+
+  this->_decrement_outstanding_counters(it);
+  return this->_sent_packets.erase(it);
+}
+
+void
+QUICLossDetector::_decrement_outstanding_counters(std::map<QUICPacketNumber, PacketInfoUPtr>::iterator it)
+{
+  if (it != this->_sent_packets.end()) {
+    // Decrement counters
+    if (it->second->handshake) {
       ink_assert(this->_handshake_outstanding.load() > 0);
       --this->_handshake_outstanding;
     }
-    if (!ite->second->ack_only) {
+    if (!it->second->ack_only) {
       ink_assert(this->_retransmittable_outstanding.load() > 0);
       --this->_retransmittable_outstanding;
     }
   }
-
-  // Remove from the list
-  this->_sent_packets.erase(packet_number);
 }
 
 ink_hrtime
diff --git a/iocore/net/quic/QUICLossDetector.h b/iocore/net/quic/QUICLossDetector.h
index 48249a1..4bb26ec 100644
--- a/iocore/net/quic/QUICLossDetector.h
+++ b/iocore/net/quic/QUICLossDetector.h
@@ -163,6 +163,9 @@ private:
   std::atomic<uint32_t> _retransmittable_outstanding;
   void _add_to_sent_packet_list(QUICPacketNumber packet_number, std::unique_ptr<PacketInfo> packet_info);
   void _remove_from_sent_packet_list(QUICPacketNumber packet_number);
+  std::map<QUICPacketNumber, PacketInfoUPtr>::iterator _remove_from_sent_packet_list(
+    std::map<QUICPacketNumber, PacketInfoUPtr>::iterator it);
+  void _decrement_outstanding_counters(std::map<QUICPacketNumber, PacketInfoUPtr>::iterator it);
 
   /*
    * Because this alarm will be reset on every packet transmission, to reduce number of events,