Skip to content

Commit 55c6947

Browse files
committed
Wave need for locking when calling FakeStrea::{body,headers,trailers}
Those return references to internal protected members, so ideally all the callers should acquire a lock before calling those. However, all the tests that use FakeStream or one of its derivatives cannot really acquire the right lock because it's a protected member of the class. We got away with this so far for a few reasons: 1. Clang thread safety annotations didn't detect this problematic pattern in the clang-14 that we are currently using (potentially because those methods actually acquired locks, even though those locks didn't actually protect much). 2. The locks are really only needed to synchronize all the waitForX methods, accesors methods like body(), headers() and trailers() are called in tests after the appropriate waitForX method was called. Disabling thread safety annotations for these methods does not actually make anything worse, because the existing implementation aren't thread safe anyways, however here are a few alternatives to disabling those that I considered and rejected at the moment: 1. Return copies of body, headers and trailers instead of references, create those copies under a lock - that would be the easiest way to let compiler know that the code is fine, but all three methods return abstract classes and currently there is no easy way to copy them (that's not to say, that copying is impossible in principle); 2. Expose the lock and require all the callers acquire it - this was my first idea of how to fix the issue, but FakeStream (and it's derivatives) is used quite a lot in tests, so this change will get quite invasive. Because it does not seem like we really need to lock those methods in practice and given that alternatives to disabling thread safety analysis on those are quite invasive, I figured I can just silence the compiler in this case. Signed-off-by: Mikhail Krinkin <[email protected]>
1 parent 41d8ccc commit 55c6947

File tree

2 files changed

+4
-9
lines changed

2 files changed

+4
-9
lines changed

test/integration/fake_upstream.cc

+1
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ AssertionResult FakeStream::waitForData(Event::Dispatcher& client_dispatcher,
276276
absl::string_view data, milliseconds timeout) {
277277
auto succeeded = waitForData(client_dispatcher, data.length(), timeout);
278278
if (succeeded) {
279+
absl::MutexLock lock(&lock_);
279280
Buffer::OwnedImpl buffer(data.data(), data.length());
280281
if (!TestUtility::buffersEqual(body(), buffer)) {
281282
return AssertionFailure() << body().toString() << " not equal to " << data;

test/integration/fake_upstream.h

+3-9
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,7 @@ class FakeStream : public Http::RequestDecoder,
7575
absl::MutexLock lock(&lock_);
7676
return body_.length();
7777
}
78-
Buffer::Instance& body() {
79-
absl::MutexLock lock(&lock_);
80-
return body_;
81-
}
78+
Buffer::Instance& body() ABSL_NO_THREAD_SAFETY_ANALYSIS { return body_; }
8279
bool complete() {
8380
absl::MutexLock lock(&lock_);
8481
return end_stream_;
@@ -97,12 +94,9 @@ class FakeStream : public Http::RequestDecoder,
9794
void encodeResetStream();
9895
void encodeMetadata(const Http::MetadataMapVector& metadata_map_vector);
9996
void readDisable(bool disable);
100-
const Http::RequestHeaderMap& headers() {
101-
absl::MutexLock lock(&lock_);
102-
return *headers_;
103-
}
97+
const Http::RequestHeaderMap& headers() ABSL_NO_THREAD_SAFETY_ANALYSIS { return *headers_; }
10498
void setAddServedByHeader(bool add_header) { add_served_by_header_ = add_header; }
105-
const Http::RequestTrailerMapPtr& trailers() { return trailers_; }
99+
const Http::RequestTrailerMapPtr& trailers() ABSL_NO_THREAD_SAFETY_ANALYSIS { return trailers_; }
106100
bool receivedData() { return received_data_; }
107101
Http::Http1StreamEncoderOptionsOptRef http1StreamEncoderOptions() {
108102
return encoder_.http1StreamEncoderOptions();

0 commit comments

Comments
 (0)