rlc_am_lte: fix potential crash when attempting to resize tx queue

under some circumstances it could happen that the RLC is configured
when SDUs are already being written to the queue. The resize
operation of the underlying container would fail in this case.

Make sure to empty the queue before doing the resize.
master
Andre Puschmann 3 years ago
parent 9230bc3b23
commit 59e1bca3f5

@ -392,6 +392,7 @@ private:
void update_notification_ack_info(uint32_t rlc_sn); void update_notification_ack_info(uint32_t rlc_sn);
void debug_state(); void debug_state();
void empty_queue_unsafe();
int required_buffer_size(const rlc_amd_retx_t& retx); int required_buffer_size(const rlc_amd_retx_t& retx);
void retransmit_pdu(uint32_t sn); void retransmit_pdu(uint32_t sn);

@ -299,6 +299,7 @@ void rlc_am_lte::rlc_am_lte_tx::set_bsr_callback(bsr_callback_t callback)
bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_) bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_)
{ {
std::lock_guard<std::mutex> lock(mutex);
if (cfg_.tx_queue_length > MAX_SDUS_PER_RLC_PDU) { if (cfg_.tx_queue_length > MAX_SDUS_PER_RLC_PDU) {
logger.error("Configuring Tx queue length of %d PDUs too big. Maximum value is %d.", logger.error("Configuring Tx queue length of %d PDUs too big. Maximum value is %d.",
cfg_.tx_queue_length, cfg_.tx_queue_length,
@ -325,6 +326,8 @@ bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_)
poll_retx_timer.set(static_cast<uint32_t>(cfg.t_poll_retx), [this](uint32_t timerid) { timer_expired(timerid); }); poll_retx_timer.set(static_cast<uint32_t>(cfg.t_poll_retx), [this](uint32_t timerid) { timer_expired(timerid); });
} }
// make sure Tx queue is empty before attempting to resize
empty_queue_unsafe();
tx_sdu_queue.resize(cfg_.tx_queue_length); tx_sdu_queue.resize(cfg_.tx_queue_length);
tx_enabled = true; tx_enabled = true;
@ -334,10 +337,10 @@ bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_)
void rlc_am_lte::rlc_am_lte_tx::stop() void rlc_am_lte::rlc_am_lte_tx::stop()
{ {
empty_queue();
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
empty_queue_unsafe();
tx_enabled = false; tx_enabled = false;
if (parent->timers != nullptr && poll_retx_timer.is_valid()) { if (parent->timers != nullptr && poll_retx_timer.is_valid()) {
@ -369,7 +372,11 @@ void rlc_am_lte::rlc_am_lte_tx::stop()
void rlc_am_lte::rlc_am_lte_tx::empty_queue() void rlc_am_lte::rlc_am_lte_tx::empty_queue()
{ {
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
empty_queue_unsafe();
}
void rlc_am_lte::rlc_am_lte_tx::empty_queue_unsafe()
{
// deallocate all SDUs in transmit queue // deallocate all SDUs in transmit queue
while (tx_sdu_queue.size() > 0) { while (tx_sdu_queue.size() > 0) {
unique_byte_buffer_t buf = tx_sdu_queue.read(); unique_byte_buffer_t buf = tx_sdu_queue.read();

Loading…
Cancel
Save