Skip to content

Commit

Permalink
[Darwin] The objc subscription callback bridge is leaked for single a…
Browse files Browse the repository at this point in the history
…ttribute subscriptions (project-chip#23061)

* [Darwin] The objc subscription callback bridge is leaked for single attribute subscriptions

* increase overall darwin build time
  • Loading branch information
jtung-apple authored and adbridge committed Nov 18, 2022
1 parent c6477fc commit d419540
Show file tree
Hide file tree
Showing 5 changed files with 13,200 additions and 10,324 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/darwin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ concurrency:
jobs:
darwin:
name: Build Darwin
timeout-minutes: 120
timeout-minutes: 210

if: github.actor != 'restyled-io[bot]'
runs-on: macos-latest
Expand Down Expand Up @@ -64,15 +64,15 @@ jobs:
.environment/gn_out/.ninja_log
.environment/pigweed-venv/*.log
- name: Run iOS Build Debug
timeout-minutes: 30
timeout-minutes: 50
working-directory: src/darwin/Framework
# For now disable unguarded-availability-new warnings because we
# internally use APIs that we are annotating as only available on
# new enough versions. Maybe we should change out deployment
# target versions instead?
run: xcodebuild -target "Matter" -sdk iphoneos OTHER_CFLAGS='${inherited} -Wno-unguarded-availability-new'
- name: Run iOS Build Release
timeout-minutes: 30
timeout-minutes: 50
working-directory: src/darwin/Framework
# For now disable unguarded-availability-new warnings because we
# internally use APIs that we are annotating as only available on
Expand All @@ -86,7 +86,7 @@ jobs:
run: defaults delete com.apple.dt.xctest.tool
continue-on-error: true
- name: Run macOS Build
timeout-minutes: 40
timeout-minutes: 70
# Enable -Werror by hand here, because the Xcode config can't
# enable it for various reasons. Keep whatever Xcode settings
# for OTHER_CFLAGS exist by using ${inherited}.
Expand Down Expand Up @@ -118,7 +118,7 @@ jobs:
run: defaults delete com.apple.dt.xctest.tool
continue-on-error: true
- name: Run Framework Tests
timeout-minutes: 15
timeout-minutes: 20
# For now disable unguarded-availability-new warnings because we
# internally use APIs that we are annotating as only available on
# new enough versions. Maybe we should change out deployment
Expand Down
13 changes: 8 additions & 5 deletions src/controller/CHIPCluster.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ using ReadResponseFailureCallback = void (*)(void * context, CHIP_ERROR err)
using ReadDoneCallback = void (*)(void * context);
using SubscriptionEstablishedCallback = void (*)(void * context);
using ResubscriptionAttemptCallback = void (*)(void * context, CHIP_ERROR aError, uint32_t aNextResubscribeIntervalMsec);
using SubscriptionOnDoneCallback = std::function<void(void)>;

class DLL_EXPORT ClusterBase
{
Expand Down Expand Up @@ -262,12 +263,13 @@ class DLL_EXPORT ClusterBase
ReadResponseFailureCallback failureCb, uint16_t minIntervalFloorSeconds, uint16_t maxIntervalCeilingSeconds,
SubscriptionEstablishedCallback subscriptionEstablishedCb = nullptr,
ResubscriptionAttemptCallback resubscriptionAttemptCb = nullptr, bool aIsFabricFiltered = true,
bool aKeepPreviousSubscriptions = false, const Optional<DataVersion> & aDataVersion = NullOptional)
bool aKeepPreviousSubscriptions = false, const Optional<DataVersion> & aDataVersion = NullOptional,
SubscriptionOnDoneCallback subscriptionDoneCb = nullptr)
{
return SubscribeAttribute<typename AttributeInfo::DecodableType, typename AttributeInfo::DecodableArgType>(
context, AttributeInfo::GetClusterId(), AttributeInfo::GetAttributeId(), reportCb, failureCb, minIntervalFloorSeconds,
maxIntervalCeilingSeconds, subscriptionEstablishedCb, resubscriptionAttemptCb, aIsFabricFiltered,
aKeepPreviousSubscriptions, aDataVersion);
aKeepPreviousSubscriptions, aDataVersion, subscriptionDoneCb);
}

template <typename DecodableType, typename DecodableArgType>
Expand All @@ -276,8 +278,9 @@ class DLL_EXPORT ClusterBase
uint16_t minIntervalFloorSeconds, uint16_t maxIntervalCeilingSeconds,
SubscriptionEstablishedCallback subscriptionEstablishedCb = nullptr,
ResubscriptionAttemptCallback resubscriptionAttemptCb = nullptr, bool aIsFabricFiltered = true,
bool aKeepPreviousSubscriptions = false,
const Optional<DataVersion> & aDataVersion = NullOptional)
bool aKeepPreviousSubscriptions = false,
const Optional<DataVersion> & aDataVersion = NullOptional,
SubscriptionOnDoneCallback subscriptionDoneCb = nullptr)
{
auto onReportCb = [context, reportCb](const app::ConcreteAttributePath & aPath, const DecodableType & aData) {
if (reportCb != nullptr)
Expand Down Expand Up @@ -311,7 +314,7 @@ class DLL_EXPORT ClusterBase
return Controller::SubscribeAttribute<DecodableType>(
&mExchangeManager, mSession.Get().Value(), mEndpoint, clusterId, attributeId, onReportCb, onFailureCb,
minIntervalFloorSeconds, maxIntervalCeilingSeconds, onSubscriptionEstablishedCb, onResubscriptionAttemptCb,
aIsFabricFiltered, aKeepPreviousSubscriptions, aDataVersion);
aIsFabricFiltered, aKeepPreviousSubscriptions, aDataVersion, subscriptionDoneCb);
}

/**
Expand Down
21 changes: 17 additions & 4 deletions src/controller/ReadInteraction.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ namespace chip {
namespace Controller {
namespace detail {

using SubscriptionOnDoneCallback = std::function<void(void)>;

template <typename DecodableAttributeType>
struct ReportAttributeParams : public app::ReadPrepareParams
{
Expand All @@ -40,6 +42,7 @@ struct ReportAttributeParams : public app::ReadPrepareParams
mOnSubscriptionEstablishedCb = nullptr;
typename TypedReadAttributeCallback<DecodableAttributeType>::OnResubscriptionAttemptCallbackType mOnResubscriptionAttemptCb =
nullptr;
SubscriptionOnDoneCallback mOnDoneCb = nullptr;
app::ReadClient::InteractionType mReportType = app::ReadClient::InteractionType::Read;
};

Expand All @@ -63,7 +66,14 @@ CHIP_ERROR ReportAttribute(Messaging::ExchangeManager * exchangeMgr, EndpointId
readParams.mpDataVersionFilterList = dataVersionFilters.get();
readParams.mDataVersionFilterListSize = 1;
}
auto onDone = [](TypedReadAttributeCallback<DecodableAttributeType> * callback) { chip::Platform::Delete(callback); };
auto onDoneCb = readParams.mOnDoneCb;
auto onDone = [onDoneCb](TypedReadAttributeCallback<DecodableAttributeType> * callback) {
if (onDoneCb)
{
onDoneCb();
}
chip::Platform::Delete(callback);
};

auto callback = chip::Platform::MakeUnique<TypedReadAttributeCallback<DecodableAttributeType>>(
clusterId, attributeId, readParams.mOnReportCb, readParams.mOnErrorCb, onDone, readParams.mOnSubscriptionEstablishedCb,
Expand Down Expand Up @@ -151,13 +161,15 @@ CHIP_ERROR SubscribeAttribute(
nullptr,
typename TypedReadAttributeCallback<DecodableAttributeType>::OnResubscriptionAttemptCallbackType onResubscriptionAttemptCb =
nullptr,
bool fabricFiltered = true, bool keepPreviousSubscriptions = false, const Optional<DataVersion> & aDataVersion = NullOptional)
bool fabricFiltered = true, bool keepPreviousSubscriptions = false, const Optional<DataVersion> & aDataVersion = NullOptional,
typename detail::SubscriptionOnDoneCallback onDoneCb = nullptr)
{
detail::ReportAttributeParams<DecodableAttributeType> params(sessionHandle);
params.mOnReportCb = onReportCb;
params.mOnErrorCb = onErrorCb;
params.mOnSubscriptionEstablishedCb = onSubscriptionEstablishedCb;
params.mOnResubscriptionAttemptCb = onResubscriptionAttemptCb;
params.mOnDoneCb = onDoneCb;
params.mMinIntervalFloorSeconds = minIntervalFloorSeconds;
params.mMaxIntervalCeilingSeconds = maxIntervalCeilingSeconds;
params.mKeepSubscriptions = keepPreviousSubscriptions;
Expand Down Expand Up @@ -185,12 +197,13 @@ CHIP_ERROR SubscribeAttribute(
onSubscriptionEstablishedCb = nullptr,
typename TypedReadAttributeCallback<typename AttributeTypeInfo::DecodableType>::OnResubscriptionAttemptCallbackType
onResubscriptionAttemptCb = nullptr,
bool fabricFiltered = true, bool keepPreviousSubscriptions = false, const Optional<DataVersion> & aDataVersion = NullOptional)
bool fabricFiltered = true, bool keepPreviousSubscriptions = false, const Optional<DataVersion> & aDataVersion = NullOptional,
typename detail::SubscriptionOnDoneCallback onDoneCb = nullptr)
{
return SubscribeAttribute<typename AttributeTypeInfo::DecodableType>(
exchangeMgr, sessionHandle, endpointId, AttributeTypeInfo::GetClusterId(), AttributeTypeInfo::GetAttributeId(), onReportCb,
onErrorCb, aMinIntervalFloorSeconds, aMaxIntervalCeilingSeconds, onSubscriptionEstablishedCb, onResubscriptionAttemptCb,
fabricFiltered, keepPreviousSubscriptions, aDataVersion);
fabricFiltered, keepPreviousSubscriptions, aDataVersion, onDoneCb);
}

namespace detail {
Expand Down
8 changes: 6 additions & 2 deletions src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <lib/support/CHIPListUtils.h>
#include <platform/CHIPDeviceLayer.h>
#include <type_traits>
#include <controller/TypedReadCallback.h>

using chip::Callback::Callback;
using chip::Callback::Cancelable;
Expand Down Expand Up @@ -189,7 +190,7 @@ subscriptionEstablished:(SubscriptionEstablishedHandler _Nullable)subscriptionEs
minInterval = [minInterval copy];
maxInterval = [maxInterval copy];
params = [params copy];
new MTR{{>attribute_data_callback_name}}CallbackSubscriptionBridge(self.callbackQueue,
__block MTR{{>attribute_data_callback_name}}CallbackSubscriptionBridge * callbackBridge = new MTR{{>attribute_data_callback_name}}CallbackSubscriptionBridge(self.callbackQueue,
self.device,
{{! This treats reportHandler as taking an id for the data. This is
not great from a type-safety perspective, of course. }}
Expand All @@ -204,9 +205,12 @@ subscriptionEstablished:(SubscriptionEstablishedHandler _Nullable)subscriptionEs
auto failureFn = Callback<DefaultFailureCallbackType>::FromCancelable(failure);

chip::Controller::{{asUpperCamelCase parent.name}}Cluster cppCluster(exchangeManager, session, self->_endpoint);
MTR{{>attribute_data_callback_name}}CallbackSubscriptionBridge * innerCallbackBridge = callbackBridge;
return cppCluster.SubscribeAttribute<TypeInfo>(successFn->mContext, successFn->mCall, failureFn->mCall, [minInterval unsignedShortValue], [maxInterval unsignedShortValue], MTR{{>attribute_data_callback_name}}CallbackSubscriptionBridge::OnSubscriptionEstablished, nil,
params == nil || params.fabricFiltered == nil || [params.fabricFiltered boolValue],
params != nil && params.keepPreviousSubscriptions != nil && [params.keepPreviousSubscriptions boolValue]
params != nil && params.keepPreviousSubscriptions != nil && [params.keepPreviousSubscriptions boolValue],
chip::NullOptional,
[innerCallbackBridge](void) { delete innerCallbackBridge; }
);
}, subscriptionEstablishedHandler);
}
Expand Down
Loading

0 comments on commit d419540

Please sign in to comment.