Fix PullUidProvider unregistering on config update

Previously, MetricsManagers would unregister themselves as a
PullUidProvider for a given ConfigKey in the destructor. This caused all
pulls to fail after a config update because the new MetricsManager would
register itself before the old MetricsManager was destructed and
unregistered. This resulted in the old MetricsManager removing the new
config since they shared the same config key. The fix is for the
PullerManager to check that the PullUidProviders are equal in the
unregister function before actually erasing it.

Test: bit statsd_test:* (wrote a failing test that now passes).
Test: statsd_localdrive to manually update a config, ensured pulls still
worked.
Bug: 154544328

Change-Id: Id7af3b3b407e24bee74fc34bd1c2b9e0575e9c9e
This commit is contained in:
Tej Singh
2020-04-20 22:04:38 -07:00
parent 87adee8718
commit 3eb9cede0b
6 changed files with 38 additions and 7 deletions

View File

@@ -252,9 +252,13 @@ void StatsPullerManager::RegisterPullUidProvider(const ConfigKey& configKey,
mPullUidProviders[configKey] = provider;
}
void StatsPullerManager::UnregisterPullUidProvider(const ConfigKey& configKey) {
void StatsPullerManager::UnregisterPullUidProvider(const ConfigKey& configKey,
wp<PullUidProvider> provider) {
std::lock_guard<std::mutex> _l(mLock);
mPullUidProviders.erase(configKey);
const auto& it = mPullUidProviders.find(configKey);
if (it != mPullUidProviders.end() && it->second == provider) {
mPullUidProviders.erase(it);
}
}
void StatsPullerManager::OnAlarmFired(int64_t elapsedTimeNs) {

View File

@@ -78,11 +78,12 @@ public:
wp<PullDataReceiver> receiver);
// Registers a pull uid provider for the config key. When pulling atoms, it will be used to
// determine which atoms to pull from.
// determine which uids to pull from.
virtual void RegisterPullUidProvider(const ConfigKey& configKey, wp<PullUidProvider> provider);
// Unregister a pull uid provider.
virtual void UnregisterPullUidProvider(const ConfigKey& configKey);
virtual void UnregisterPullUidProvider(const ConfigKey& configKey,
wp<PullUidProvider> provider);
// Verify if we know how to pull for this matcher
bool PullerForMatcherExists(int tagId) const;
@@ -180,6 +181,8 @@ private:
FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation);
FRIEND_TEST(StatsLogProcessorTest, TestPullUidProviderSetOnConfigUpdate);
};
} // namespace statsd

View File

@@ -189,7 +189,7 @@ MetricsManager::~MetricsManager() {
StateManager::getInstance().unregisterListener(atomId, it);
}
}
mPullerManager->UnregisterPullUidProvider(mConfigKey);
mPullerManager->UnregisterPullUidProvider(mConfigKey, this);
VLOG("~MetricsManager()");
}

View File

@@ -528,7 +528,7 @@ TEST(MetricsManagerTest, TestLogSources) {
}));
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterPullUidProvider(kConfigKey, _)).Times(1);
EXPECT_CALL(*pullerManager, UnregisterPullUidProvider(kConfigKey)).Times(1);
EXPECT_CALL(*pullerManager, UnregisterPullUidProvider(kConfigKey, _)).Times(1);
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;

View File

@@ -301,6 +301,29 @@ TEST(StatsLogProcessorTest, TestOnDumpReportEraseData) {
EXPECT_TRUE(noData);
}
TEST(StatsLogProcessorTest, TestPullUidProviderSetOnConfigUpdate) {
// Setup simple config key corresponding to empty config.
sp<UidMap> m = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> subscriberAlarmMonitor;
StatsLogProcessor p(
m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
[](const ConfigKey& key) { return true; },
[](const int&, const vector<int64_t>&) { return true; });
ConfigKey key(3, 4);
StatsdConfig config = MakeConfig(false);
p.OnConfigUpdated(0, key, config);
EXPECT_NE(pullerManager->mPullUidProviders.find(key), pullerManager->mPullUidProviders.end());
config.add_default_pull_packages("AID_STATSD");
p.OnConfigUpdated(5, key, config);
EXPECT_NE(pullerManager->mPullUidProviders.find(key), pullerManager->mPullUidProviders.end());
p.OnConfigRemoved(key);
EXPECT_EQ(pullerManager->mPullUidProviders.find(key), pullerManager->mPullUidProviders.end());
}
TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) {
int uid = 1111;

View File

@@ -44,7 +44,8 @@ public:
vector<std::shared_ptr<LogEvent>>* data, bool useUids));
MOCK_METHOD2(RegisterPullUidProvider,
void(const ConfigKey& configKey, wp<PullUidProvider> provider));
MOCK_METHOD1(UnregisterPullUidProvider, void(const ConfigKey& configKey));
MOCK_METHOD2(UnregisterPullUidProvider,
void(const ConfigKey& configKey, wp<PullUidProvider> provider));
};
class MockUidMap : public UidMap {