From 12357762f752ebce8e0b50a02f4e804c344018a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20Kr=C3=B3lik?= <66667989+Damian-Nordic@users.noreply.github.com> Date: Wed, 26 Jan 2022 15:46:18 +0100 Subject: [PATCH] [op-creds] Fix RemoveFabric command (#13869) RemoveFabric command called for the fabric that is used to process the message crashes in SessionHolder. The reason is that sessions for the removed fabric are expired when the command's exchange is closed after sending the response and that triggers closing all associated session holders. An exchange's session holder closes the exchange which in this case results in an attempt to close an exchange that is in the middle of closing... --- .../operational-credentials-server.cpp | 12 +++++++----- src/messaging/ExchangeContext.cpp | 7 +++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp b/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp index f91af0517ab9c2..4459098530ae9b 100644 --- a/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp +++ b/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp @@ -373,12 +373,14 @@ bool emberAfOperationalCredentialsClusterRemoveFabricCallback(app::CommandHandle FabricIndex currentFabricIndex = commandObj->GetAccessingFabricIndex(); if (currentFabricIndex == fabricBeingRemoved) { - // If the current fabric is being removed, expiring all the secure sessions causes crashes as - // the message sent by emberAfSendImmediateDefaultResponse() is still in the queue. Also, RMP - // retries to send the message and runs into issues. - // We are hijacking the exchange delegate here (as no more messages should be received on this exchange), - // and wait for it to close, before expiring the secure sessions for the fabric. + // If the current fabric is being removed, don't expire the secure sessions immediately as they are + // still needed to send a pending message generated by emberAfSendImmediateDefaultResponse(). + // Hijack the exchange delegate here (as no more messages should be received on this exchange), + // and wait for it to close, before expiring the secure sessions for the fabric. Also, suppress MRP + // usage since the MRP engine still holds an exchange even after it's closed, and the engine references + // the associated session object. // TODO: https://github.com/project-chip/connectedhomeip/issues/9642 + ec->SetAutoRequestAck(false); ec->SetDelegate(&gFabricCleanupExchangeDelegate); } else diff --git a/src/messaging/ExchangeContext.cpp b/src/messaging/ExchangeContext.cpp index a2dc5cbfa75dc7..20d308a53ad936 100644 --- a/src/messaging/ExchangeContext.cpp +++ b/src/messaging/ExchangeContext.cpp @@ -325,6 +325,13 @@ bool ExchangeContext::MatchExchange(const SessionHandle & session, const PacketH void ExchangeContext::OnSessionReleased() { + if (mFlags.Has(Flags::kFlagClosed)) + { + // Exchange is already being closed. It may occur when closing an exchange after sending + // RemoveFabric response which triggers removal of all sessions for the given fabric. + return; + } + ExchangeHandle ref(*this); if (IsResponseExpected())