Skip to content
This repository was archived by the owner on Jul 31, 2023. It is now read-only.

Commit a4b19bc

Browse files
authored
Check that WithContext is constructed and destructed on the same thread. (#206)
This only happens in debug mode (!NDEBUG). Add a death test for it.
1 parent c338d91 commit a4b19bc

3 files changed

Lines changed: 41 additions & 2 deletions

File tree

opencensus/context/internal/with_context.cc

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,42 @@
1414

1515
#include "opencensus/context/with_context.h"
1616

17+
#include <cassert>
1718
#include <utility>
1819

1920
#include "opencensus/context/context.h"
2021

2122
namespace opencensus {
2223
namespace context {
2324

24-
WithContext::WithContext(const Context& ctx) : swapped_context_(ctx) {
25+
WithContext::WithContext(const Context& ctx)
26+
: swapped_context_(ctx)
27+
#ifndef NDEBUG
28+
,
29+
original_context_(Context::InternalMutableCurrent())
30+
#endif
31+
{
2532
using std::swap;
2633
swap(*Context::InternalMutableCurrent(), swapped_context_);
2734
}
2835

29-
WithContext::WithContext(Context&& ctx) : swapped_context_(std::move(ctx)) {
36+
WithContext::WithContext(Context&& ctx)
37+
: swapped_context_(std::move(ctx))
38+
#ifndef NDEBUG
39+
,
40+
original_context_(Context::InternalMutableCurrent())
41+
#endif
42+
{
3043
using std::swap;
3144
swap(*Context::InternalMutableCurrent(), swapped_context_);
3245
}
3346

3447
WithContext::~WithContext() {
48+
#ifndef NDEBUG
49+
assert(original_context_ == Context::InternalMutableCurrent() &&
50+
"WithContext must be destructed on the same thread as it was "
51+
"constructed.");
52+
#endif
3553
using std::swap;
3654
swap(*Context::InternalMutableCurrent(), swapped_context_);
3755
}

opencensus/context/internal/with_context_test.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "opencensus/context/with_context.h"
1616

1717
#include <iostream>
18+
#include <thread>
1819

1920
#include "gtest/gtest.h"
2021
#include "opencensus/context/context.h"
@@ -34,4 +35,21 @@ TEST(WithContextTest, WithContextMovable) {
3435
opencensus::context::WithContext wc(std::move(ctx));
3536
}
3637

38+
#ifndef NDEBUG
39+
TEST(WithContextDeathTest, DestructorOnWrongThread) {
40+
opencensus::context::Context ctx = opencensus::context::Context::Current();
41+
EXPECT_DEATH_IF_SUPPORTED(
42+
{
43+
auto* wc = new opencensus::context::WithContext(ctx);
44+
std::thread t([wc]() {
45+
// Running the destructor in a different thread corrupts its
46+
// thread-local Context. In debug mode, it assert()s.
47+
delete wc;
48+
});
49+
t.join();
50+
},
51+
"must be destructed on the same thread");
52+
}
53+
#endif
54+
3755
} // namespace

opencensus/context/with_context.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class WithContext {
4040
WithContext& operator=(WithContext&&) = delete;
4141

4242
Context swapped_context_;
43+
#ifndef NDEBUG
44+
const Context* original_context_;
45+
#endif
4346
};
4447

4548
} // namespace context

0 commit comments

Comments
 (0)