Skip to content

Commit 23f0824

Browse files
Fix management of the mNumReportsInFlight count in reporting engine. (#24093)
If a ReadHandler failed out of SendReportData (e.g. because the session it's on had been marked as defunct), we would increment mNumReportsInFlight and never decrement it. After this happened CHIP_IM_MAX_REPORTS_IN_FLIGHT times (4 by default), we would stop being able to send out any more data reports. This situation is pretty easy to trigger as follows: 1. Use chip-tool to commission a device with node id 17. 2. Start chip-tool interactive mode. 3. Run the following commands in interactive mode: onoff subscribe on-off 0 60 17 1 --keepSubscriptions true onoff subscribe on-off 0 60 17 1 --keepSubscriptions true onoff subscribe on-off 0 60 17 1 --keepSubscriptions true onoff subscribe on-off 0 60 17 1 --keepSubscriptions true onoff subscribe on-off 0 2 17 1 --keepSubscriptions true 4. quit interactive mode (Ctrl-C or quit() command). 5. Wait 60 seconds for all the subscriptions to error out. After this the device will no longer respond with data reports to any read or subscribe requests.
1 parent 918d3ad commit 23f0824

File tree

3 files changed

+26
-15
lines changed

3 files changed

+26
-15
lines changed

src/app/ReadHandler.cpp

+20-15
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ CHIP_ERROR ReadHandler::SendStatusReport(Protocols::InteractionModel::Status aSt
206206
CHIP_ERROR ReadHandler::SendReportData(System::PacketBufferHandle && aPayload, bool aMoreChunks)
207207
{
208208
VerifyOrReturnLogError(IsReportable(), CHIP_ERROR_INCORRECT_STATE);
209+
VerifyOrDie(!IsAwaitingReportResponse()); // Should not be reportable!
209210
if (IsPriming() || IsChunkedReport())
210211
{
211212
mSessionHandle.Grab(mExchangeCtx->GetSessionHandle());
@@ -230,27 +231,31 @@ CHIP_ERROR ReadHandler::SendReportData(System::PacketBufferHandle && aPayload, b
230231
mCurrentReportsBeginGeneration = InteractionModelEngine::GetInstance()->GetReportingEngine().GetDirtySetGeneration();
231232
}
232233
SetStateFlag(ReadHandlerFlags::ChunkedReport, aMoreChunks);
233-
bool noResponseExpected = IsType(InteractionType::Read) && !aMoreChunks;
234-
if (!noResponseExpected)
235-
{
236-
MoveToState(HandlerState::AwaitingReportResponse);
237-
}
234+
bool responseExpected = IsType(InteractionType::Subscribe) || aMoreChunks;
238235

239236
mExchangeCtx->UseSuggestedResponseTimeout(app::kExpectedIMProcessingTime);
240-
CHIP_ERROR err =
241-
mExchangeCtx->SendMessage(Protocols::InteractionModel::MsgType::ReportData, std::move(aPayload),
242-
Messaging::SendFlags(noResponseExpected ? Messaging::SendMessageFlags::kNone
243-
: Messaging::SendMessageFlags::kExpectResponse));
244-
if (err == CHIP_NO_ERROR && noResponseExpected)
245-
{
246-
InteractionModelEngine::GetInstance()->GetReportingEngine().OnReportConfirm();
247-
}
248-
237+
CHIP_ERROR err = mExchangeCtx->SendMessage(Protocols::InteractionModel::MsgType::ReportData, std::move(aPayload),
238+
responseExpected ? Messaging::SendMessageFlags::kExpectResponse
239+
: Messaging::SendMessageFlags::kNone);
249240
if (err == CHIP_NO_ERROR)
250241
{
242+
if (responseExpected)
243+
{
244+
MoveToState(HandlerState::AwaitingReportResponse);
245+
}
246+
else
247+
{
248+
// Make sure we're not treated as an in-flight report waiting for a
249+
// response by the reporting engine.
250+
InteractionModelEngine::GetInstance()->GetReportingEngine().OnReportConfirm();
251+
}
252+
251253
if (IsType(InteractionType::Subscribe) && !IsPriming())
252254
{
253-
err = RefreshSubscribeSyncTimer();
255+
// Ignore the error from RefreshSubscribeSyncTimer. If we've
256+
// successfully sent the message, we need to return success from
257+
// this method.
258+
RefreshSubscribeSyncTimer();
254259
}
255260
}
256261
if (!aMoreChunks)

src/app/ReadHandler.h

+2
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ class ReadHandler : public Messaging::ExchangeDelegate
252252
* @retval #Others If fails to send report data
253253
* @retval #CHIP_NO_ERROR On success.
254254
*
255+
* If an error is returned, the ReadHandler guarantees that it is not in
256+
* a state where it's waiting for a response.
255257
*/
256258
CHIP_ERROR SendReportData(System::PacketBufferHandle && aPayload, bool aMoreChunks);
257259

src/app/reporting/Engine.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,10 @@ CHIP_ERROR Engine::SendReport(ReadHandler * apReadHandler, System::PacketBufferH
848848
// We can only have 1 report in flight for any given read - increment and break out.
849849
mNumReportsInFlight++;
850850
err = apReadHandler->SendReportData(std::move(aPayload), aHasMoreChunks);
851+
if (err != CHIP_NO_ERROR)
852+
{
853+
--mNumReportsInFlight;
854+
}
851855
return err;
852856
}
853857

0 commit comments

Comments
 (0)