From 6f7767a8ae9519d8fb87153c575ea345e79faef4 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Sun, 13 Aug 2023 10:43:26 -0700 Subject: [PATCH] [mesh-forwarder] disallow new message eviction in `ApplyDirectTxQueueLimit()` (#9348) This commit updates the `ApplyDirectTxQueueLimit()` method. We mark the "do not evict" flag on the newly queued `aMessage` so that it will not be removed from `RemoveAgedMessages()`. This protects against the unlikely case where the newly queued `aMessage` may already be aged due to execution being interrupted for a long time between the queuing of the message in `SendMessage()` and the call to `ApplyDirectTxQueueLimit()`. This protects against the message being potentially removed and freed twice. --- src/core/thread/mesh_forwarder.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 1e80d40d5..343e9e721 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -411,7 +411,7 @@ Error MeshForwarder::RemoveAgedMessages(void) nextMessage = message->GetNext(); // Exclude the current message being sent `mSendMessage`. - if ((message == mSendMessage) || !message->IsDirectTransmission()) + if ((message == mSendMessage) || !message->IsDirectTransmission() || message->GetDoNotEvict()) { continue; } @@ -494,9 +494,27 @@ void MeshForwarder::ApplyDirectTxQueueLimit(Message &aMessage) VerifyOrExit(IsDirectTxQueueOverMaxFrameThreshold()); #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE - if (RemoveAgedMessages() == kErrorNone) { - VerifyOrExit(IsDirectTxQueueOverMaxFrameThreshold()); + bool originalEvictFlag = aMessage.GetDoNotEvict(); + Error error; + + // We mark the "do not evict" flag on the new `aMessage` so + // that it will not be removed from `RemoveAgedMessages()`. + // This protects against the unlikely case where the newly + // queued `aMessage` may already be aged due to execution + // being interrupted for a long time between the queuing of + // the message and the `ApplyDirectTxQueueLimit()` call. We + // do not want the message to be potentially removed and + // freed twice. + + aMessage.SetDoNotEvict(true); + error = RemoveAgedMessages(); + aMessage.SetDoNotEvict(originalEvictFlag); + + if (error == kErrorNone) + { + VerifyOrExit(IsDirectTxQueueOverMaxFrameThreshold()); + } } #endif