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())