Skip to content

Commit a33a746

Browse files
abhinavdangetichiyoung
authored andcommitted
MB-19226: Address potential data races in the warmup code
Context: warmupState, estimatedWarmupCount, warmup, metadata As reported by ThreadSanitizer: WARNING: ThreadSanitizer: data race (pid=7023) Write of size 8 at 0x7d240000d5e0 by thread T7: #0 Warmup::checkForAccessLog() /home/daver/repos/couchbase/server/ep-engine/src/warmup.cc:590 (ep.so+0x0000002d1ffc) #1 WarmupCheckforAccessLog::run() /home/daver/repos/couchbase/server/ep-engine/src/warmup.h:303 (ep.so+0x0000002e2bfb) #2 ExecutorThread::run() /home/daver/repos/couchbase/server/ep-engine/src/executorthread.cc:106 (ep.so+0x0000001e34f9) #3 launch_executor_thread(void*) /home/daver/repos/couchbase/server/ep-engine/src/executorthread.cc:34 (ep.so+0x0000001e2b7a) #4 platform_thread_wrap /home/daver/repos/couchbase/server/platform/src/cb_pthreads.c:19 (libplatform.so.0.1.0+0x0000000035dc) Previous read of size 8 at 0x7d240000d5e0 by main thread (mutexes: write M699180732592992152): #0 Warmup::addStats(void (*)(char const*, unsigned short, char const*, unsigned int, void const*), void const*) const /home/daver/repos/couchbase/server/ep-engine/src/warmup.cc:893 (ep.so+0x0000002d6086) #1 EventuallyPersistentEngine::getStats(void const*, char const*, int, void (*)(char const*, unsigned short, char const*, unsigned int, void const*)) /home/daver/repos/couchbase/server/ep-engine/src/ep_engine.cc:4422 (ep.so+0x000000151813) #2 EvpGetStats(engine_interface*, void const*, char const*, int, void (*)(char const*, unsigned short, char const*, unsigned int, void const*)) /home/daver/repos/couchbase/server/ep-engine/src/ep_engine.cc:214 (ep.so+0x0000001367b2) #3 mock_get_stats /home/daver/repos/couchbase/server/memcached/programs/engine_testapp/engine_testapp.c:194 (engine_testapp+0x0000004bde63) #4 wait_for_warmup_complete(engine_interface*, engine_interface_v1*) /home/daver/repos/couchbase/server/ep-engine/tests/ep_test_apis.cc:898 (ep_testsuite.so+0x0000000ead95) #5 test_setup(engine_interface*, engine_interface_v1*) /home/daver/repos/couchbase/server/ep-engine/tests/ep_testsuite.cc:168 (ep_testsuite.so+0x0000000237d3) #6 execute_test /home/daver/repos/couchbase/server/memcached/programs/engine_testapp/engine_testapp.c:1037 (engine_testapp+0x0000004ba82b) #7 main /home/daver/repos/couchbase/server/memcached/programs/engine_testapp/engine_testapp.c:1296 (engine_testapp+0x0000004b8861) Change-Id: If96933b3b8b0aa1ed75073a0d8d629f138da081f Reviewed-on: http://review.couchbase.org/62916 Well-Formed: buildbot <[email protected]> Reviewed-by: Will Gardner <[email protected]> Tested-by: buildbot <[email protected]>
1 parent 9cf8af7 commit a33a746

File tree

2 files changed

+30
-28
lines changed

2 files changed

+30
-28
lines changed

src/warmup.cc

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ const int WarmupState::LoadingData = 7;
132132
const int WarmupState::Done = 8;
133133

134134
const char *WarmupState::toString(void) const {
135-
return getStateDescription(state);
135+
return getStateDescription(state.load());
136136
}
137137

138138
const char *WarmupState::getStateDescription(int st) const {
@@ -164,10 +164,10 @@ void WarmupState::transition(int to, bool allowAnystate) {
164164
if (allowAnystate || legalTransition(to)) {
165165
std::stringstream ss;
166166
ss << "Warmup transition from state \""
167-
<< getStateDescription(state) << "\" to \""
167+
<< getStateDescription(state.load()) << "\" to \""
168168
<< getStateDescription(to) << "\"";
169169
LOG(EXTENSION_LOG_DEBUG, "%s", ss.str().c_str());
170-
state = to;
170+
state.store(to);
171171
} else {
172172
// Throw an exception to make it possible to test the logic ;)
173173
std::stringstream ss;
@@ -177,7 +177,7 @@ void WarmupState::transition(int to, bool allowAnystate) {
177177
}
178178

179179
bool WarmupState::legalTransition(int to) const {
180-
switch (state) {
180+
switch (state.load()) {
181181
case Initialize:
182182
return (to == CreateVBuckets);
183183
case CreateVBuckets:
@@ -384,12 +384,12 @@ Warmup::~Warmup() {
384384

385385
void Warmup::setEstimatedWarmupCount(size_t to)
386386
{
387-
estimatedWarmupCount = to;
387+
estimatedWarmupCount.store(to);
388388
}
389389

390390
size_t Warmup::getEstimatedItemCount()
391391
{
392-
return estimatedItemCount;
392+
return estimatedItemCount.load();
393393
}
394394

395395
void Warmup::start(void)
@@ -587,9 +587,9 @@ void Warmup::scheduleCheckForAccessLog()
587587

588588
void Warmup::checkForAccessLog()
589589
{
590-
metadata = gethrtime() - startTime;
590+
metadata.store(gethrtime() - startTime);
591591
LOG(EXTENSION_LOG_WARNING, "metadata loaded in %s",
592-
hrtime2text(metadata).c_str());
592+
hrtime2text(metadata.load()).c_str());
593593

594594
if (store->maybeEnableTraffic()) {
595595
transition(WarmupState::Done);
@@ -629,7 +629,6 @@ void Warmup::scheduleLoadingAccessLog()
629629

630630
void Warmup::loadingAccessLog(uint16_t shardId)
631631
{
632-
633632
LoadStorageKVPairCallback *load_cb =
634633
new LoadStorageKVPairCallback(store, true, state.getState());
635634
bool success = false;
@@ -799,7 +798,7 @@ void Warmup::done()
799798
setWarmupTime();
800799
store->warmupCompleted();
801800
LOG(EXTENSION_LOG_WARNING, "warmup completed in %s",
802-
hrtime2text(warmup).c_str());
801+
hrtime2text(warmup.load()).c_str());
803802
}
804803
}
805804

@@ -890,32 +889,36 @@ void Warmup::addStats(ADD_STAT add_stat, const void *c) const
890889
addStat("min_item_threshold",
891890
stats.warmupNumReadCap * 100.0, add_stat, c);
892891

893-
if (metadata > 0) {
894-
addStat("keys_time", metadata / 1000, add_stat, c);
892+
hrtime_t md_time = metadata.load();
893+
if (md_time > 0) {
894+
addStat("keys_time", md_time / 1000, add_stat, c);
895895
}
896896

897-
if (warmup > 0) {
898-
addStat("time", warmup / 1000, add_stat, c);
897+
hrtime_t w_time = warmup.load();
898+
if (w_time > 0) {
899+
addStat("time", w_time / 1000, add_stat, c);
899900
}
900901

901-
if (estimatedItemCount == std::numeric_limits<size_t>::max()) {
902+
size_t itemCount = estimatedItemCount.load();
903+
if (itemCount == std::numeric_limits<size_t>::max()) {
902904
addStat("estimated_key_count", "unknown", add_stat, c);
903905
} else {
904-
if (estimateTime != 0) {
905-
addStat("estimate_time", estimateTime / 1000, add_stat, c);
906+
hrtime_t e_time = estimateTime.load();
907+
if (e_time != 0) {
908+
addStat("estimate_time", e_time / 1000, add_stat, c);
906909
}
907-
addStat("estimated_key_count", estimatedItemCount, add_stat, c);
910+
addStat("estimated_key_count", itemCount, add_stat, c);
908911
}
909912

910913
if (corruptAccessLog) {
911914
addStat("access_log", "corrupt", add_stat, c);
912915
}
913916

914-
if (estimatedWarmupCount == std::numeric_limits<size_t>::max()) {
917+
size_t warmupCount = estimatedWarmupCount.load();
918+
if (warmupCount == std::numeric_limits<size_t>::max()) {
915919
addStat("estimated_value_count", "unknown", add_stat, c);
916920
} else {
917-
addStat("estimated_value_count", estimatedWarmupCount,
918-
add_stat, c);
921+
addStat("estimated_value_count", warmupCount, add_stat, c);
919922
}
920923
} else {
921924
addStat(NULL, "disabled", add_stat, c);

src/warmup.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class WarmupState {
4747
int getState(void) const { return state; }
4848

4949
private:
50-
int state;
50+
AtomicValue<int> state;
5151
const char *getStateDescription(int val) const;
5252
bool legalTransition(int to) const;
5353
friend std::ostream& operator<< (std::ostream& out,
@@ -119,8 +119,6 @@ class Warmup {
119119
void start(void);
120120
void stop(void);
121121

122-
const WarmupState &getState(void) const { return state; }
123-
124122
void setEstimatedWarmupCount(size_t num);
125123

126124
size_t getEstimatedItemCount();
@@ -130,7 +128,7 @@ class Warmup {
130128
hrtime_t getTime(void) { return warmup; }
131129

132130
void setWarmupTime(void) {
133-
warmup = gethrtime() - startTime;
131+
warmup.store(gethrtime() - startTime);
134132
}
135133

136134
size_t doWarmup(MutationLog &lf, const std::map<uint16_t,
@@ -174,11 +172,12 @@ class Warmup {
174172
void transition(int to, bool force=false);
175173

176174
WarmupState state;
175+
177176
EventuallyPersistentStore *store;
178177
size_t taskId;
179178
hrtime_t startTime;
180-
hrtime_t metadata;
181-
hrtime_t warmup;
179+
AtomicValue<hrtime_t> metadata;
180+
AtomicValue<hrtime_t> warmup;
182181

183182
std::vector<vbucket_state *> allVbStates;
184183
std::map<uint16_t, vbucket_state> *shardVbStates;
@@ -191,7 +190,7 @@ class Warmup {
191190
bool cleanShutdown;
192191
bool corruptAccessLog;
193192
AtomicValue<bool> warmupComplete;
194-
size_t estimatedWarmupCount;
193+
AtomicValue<size_t> estimatedWarmupCount;
195194

196195
DISALLOW_COPY_AND_ASSIGN(Warmup);
197196
};

0 commit comments

Comments
 (0)