diff --git a/modules/pacing/pacing_controller.cc b/modules/pacing/pacing_controller.cc index d580c2c349..5ef10db04f 100644 --- a/modules/pacing/pacing_controller.cc +++ b/modules/pacing/pacing_controller.cc @@ -193,7 +193,15 @@ void PacingController::SetProbingEnabled(bool enabled) { void PacingController::SetPacingRates(DataRate pacing_rate, DataRate padding_rate) { - RTC_DCHECK_GT(pacing_rate, DataRate::Zero()); + static constexpr DataRate kMaxRate = DataRate::KilobitsPerSec(100'000); + RTC_CHECK_GT(pacing_rate, DataRate::Zero()); + RTC_CHECK_GE(padding_rate, DataRate::Zero()); + if (pacing_rate > kMaxRate || padding_rate > kMaxRate) { + RTC_LOG(LS_WARNING) << "Very high pacing rates ( > " << kMaxRate.kbps() + << " kbps) configured: pacing = " << pacing_rate.kbps() + << " kbps, padding = " << padding_rate.kbps() + << " kbps."; + } media_rate_ = pacing_rate; padding_rate_ = padding_rate; pacing_bitrate_ = pacing_rate; @@ -478,7 +486,12 @@ void PacingController::ProcessPackets() { } DataSize data_sent = DataSize::Zero(); - while (true) { + // Circuit breaker, making sure main loop isn't forever. + static constexpr int kMaxIterations = 1 << 16; + int iteration = 0; + int packets_sent = 0; + int padding_packets_generated = 0; + for (; iteration < kMaxIterations; ++iteration) { // Fetch packet, so long as queue is not empty or budget is not // exhausted. std::unique_ptr rtp_packet = @@ -490,6 +503,7 @@ void PacingController::ProcessPackets() { std::vector> padding_packets = packet_sender_->GeneratePadding(padding_to_add); if (!padding_packets.empty()) { + padding_packets_generated += padding_packets.size(); for (auto& packet : padding_packets) { EnqueuePacket(std::move(packet)); } @@ -520,6 +534,7 @@ void PacingController::ProcessPackets() { EnqueuePacket(std::move(packet)); } data_sent += packet_size; + ++packets_sent; // Send done, update send time. OnPacketSent(packet_type, packet_size, now); @@ -546,6 +561,19 @@ void PacingController::ProcessPackets() { } } + if (iteration >= kMaxIterations) { + // Circuit break activated. Log warning, adjust send time and return. + // TODO(sprang): Consider completely clearing state. + RTC_LOG(LS_ERROR) << "PacingController exceeded max iterations in " + "send-loop: packets sent = " + << packets_sent << ", padding packets generated = " + << padding_packets_generated + << ", bytes sent = " << data_sent.bytes(); + last_send_time_ = now; + last_process_time_ = now; + return; + } + if (is_probing) { probing_send_failure_ = data_sent == DataSize::Zero(); if (!probing_send_failure_) {