diff --git a/src/inet/UDPEndPointImplLwIP.cpp b/src/inet/UDPEndPointImplLwIP.cpp index 2a46a64217cc20..edc409e73c9e8d 100644 --- a/src/inet/UDPEndPointImplLwIP.cpp +++ b/src/inet/UDPEndPointImplLwIP.cpp @@ -252,17 +252,22 @@ void UDPEndPointImplLwIP::CloseImpl() mUDP = nullptr; mLwIPEndPointType = LwIPEndPointType::Unknown; - // In case that there is a UDPEndPointImplLwIP::LwIPReceiveUDPMessage + // If there is a UDPEndPointImplLwIP::LwIPReceiveUDPMessage // event pending in the event queue (SystemLayer::ScheduleLambda), we // schedule a release call to the end of the queue, to ensure that the // queued pointer to UDPEndPointImplLwIP is not dangling. - Retain(); - CHIP_ERROR err = GetSystemLayer().ScheduleLambda([this] { Release(); }); - if (err != CHIP_NO_ERROR) + if (mDelayRelease == true) { - ChipLogError(Inet, "Unable scedule lambda: %" CHIP_ERROR_FORMAT, err.Format()); - // There is nothing we can do here, accept the chance of racing - Release(); + mDelayRelease = false; + + Retain(); + CHIP_ERROR err = GetSystemLayer().ScheduleLambda([this] { Release(); }); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Inet, "Unable scedule lambda: %" CHIP_ERROR_FORMAT, err.Format()); + // There is nothing we can do here, accept the chance of racing + Release(); + } } } @@ -278,6 +283,9 @@ void UDPEndPointImplLwIP::Free() void UDPEndPointImplLwIP::HandleDataReceived(System::PacketBufferHandle && msg, IPPacketInfo * pktInfo) { + // Clear mDelayRelease flag so that we don't need to delay release of current UDPEndPoint. + mDelayRelease = false; + if ((mState == State::kListening) && (OnMessageReceived != nullptr)) { if (pktInfo != nullptr) @@ -391,6 +399,10 @@ void UDPEndPointImplLwIP::LwIPReceiveUDPMessage(void * arg, struct udp_pcb * pcb pktInfo->SrcPort = port; pktInfo->DestPort = pcb->local_port; + // Set mDelayRelease flag to delay release of this UDP EndPoint until HandleDataReceived is + // called on this UDP EndPoint. + ep->mDelayRelease = true; + CHIP_ERROR err = ep->GetSystemLayer().ScheduleLambda([ep, p = System::LwIPPacketBufferView::UnsafeGetLwIPpbuf(buf), pktInfo] { ep->HandleDataReceived(System::PacketBufferHandle::Adopt(p), pktInfo); }); @@ -402,6 +414,8 @@ void UDPEndPointImplLwIP::LwIPReceiveUDPMessage(void * arg, struct udp_pcb * pcb } else { + ep->mDelayRelease = false; + // If ScheduleLambda() succeeded, `pktInfo` will be deleted in `HandleDataReceived`. // Otherwise we delete it here. Platform::Delete(pktInfo); diff --git a/src/inet/UDPEndPointImplLwIP.h b/src/inet/UDPEndPointImplLwIP.h index 7bc523c913ff3a..21213c77e976e9 100644 --- a/src/inet/UDPEndPointImplLwIP.h +++ b/src/inet/UDPEndPointImplLwIP.h @@ -61,6 +61,7 @@ class UDPEndPointImplLwIP : public UDPEndPoint, public EndPointStateLwIP static void LwIPReceiveUDPMessage(void * arg, struct udp_pcb * pcb, struct pbuf * p, const ip_addr_t * addr, u16_t port); udp_pcb * mUDP; // LwIP User datagram protocol (UDP) control block. + bool mDelayRelease = false; }; using UDPEndPointImpl = UDPEndPointImplLwIP;