Skip to content

Commit f74731f

Browse files
committed
fix review #3
1 parent 35fb6a1 commit f74731f

2 files changed

Lines changed: 69 additions & 29 deletions

File tree

src/butil/iobuf_inl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ void remove_tls_block_chain();
603603

604604
IOBuf::Block* acquire_tls_block();
605605

606-
inline bool is_in_tls_block_chain(IOBuf::Block* head, IOBuf::Block* b) {
606+
static inline bool is_in_tls_block_chain(IOBuf::Block* head, IOBuf::Block* b) {
607607
for (IOBuf::Block* p = head; p != NULL; p = p->u.portal_next) {
608608
if (p == b) {
609609
return true;

test/iobuf_unittest.cpp

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2001,19 +2001,27 @@ static void cleanup_corrupted_tls_chain(int drain_times) {
20012001
dec_ref_distinct_blocks(b1, b2, b3);
20022002
}
20032003

2004+
struct CycleRegressionResult {
2005+
bool setup_ok;
2006+
bool has_cycle;
2007+
};
2008+
20042009
static void* double_return_release_tls_block_head_thread(void* arg) {
2005-
bool* has_cycle = static_cast<bool*>(arg);
2010+
CycleRegressionResult* result = static_cast<CycleRegressionResult*>(arg);
2011+
result->setup_ok = false;
2012+
result->has_cycle = false;
20062013
butil::iobuf::remove_tls_block_chain();
20072014

20082015
butil::IOBuf::Block* b = butil::iobuf::acquire_tls_block();
20092016
if (!b) {
20102017
return NULL;
20112018
}
2019+
result->setup_ok = true;
20122020
butil::iobuf::release_tls_block(b);
20132021
butil::iobuf::release_tls_block(b);
20142022

20152023
if (tls_block_chain_has_cycle()) {
2016-
*has_cycle = true;
2024+
result->has_cycle = true;
20172025
cleanup_corrupted_tls_chain(2);
20182026
} else {
20192027
butil::iobuf::remove_tls_block_chain();
@@ -2022,20 +2030,24 @@ static void* double_return_release_tls_block_head_thread(void* arg) {
20222030
}
20232031

20242032
TEST_F(IOBufTest, regression_3243_release_tls_block_head_no_cycle) {
2025-
bool has_cycle = false;
2033+
CycleRegressionResult result = {false, false};
20262034
pthread_t tid;
20272035
ASSERT_EQ(0, pthread_create(&tid, NULL,
20282036
double_return_release_tls_block_head_thread,
2029-
&has_cycle));
2037+
&result));
20302038
ASSERT_EQ(0, pthread_join(tid, NULL));
20312039

2032-
EXPECT_FALSE(has_cycle)
2040+
ASSERT_TRUE(result.setup_ok)
2041+
<< "Failed to allocate a TLS block for regression setup.";
2042+
EXPECT_FALSE(result.has_cycle)
20332043
<< "release_tls_block() created a cycle when the same block was "
20342044
"returned twice while already cached in TLS. (GitHub issue #3243)";
20352045
}
20362046

20372047
static void* double_return_release_tls_block_non_head_thread(void* arg) {
2038-
bool* has_cycle = static_cast<bool*>(arg);
2048+
CycleRegressionResult* result = static_cast<CycleRegressionResult*>(arg);
2049+
result->setup_ok = false;
2050+
result->has_cycle = false;
20392051
butil::iobuf::remove_tls_block_chain();
20402052

20412053
butil::IOBuf::Block* tail = butil::iobuf::acquire_tls_block();
@@ -2044,6 +2056,7 @@ static void* double_return_release_tls_block_non_head_thread(void* arg) {
20442056
dec_ref_distinct_blocks(tail, head);
20452057
return NULL;
20462058
}
2059+
result->setup_ok = true;
20472060

20482061
butil::iobuf::release_tls_block(tail);
20492062
butil::iobuf::release_tls_block(head);
@@ -2052,7 +2065,7 @@ static void* double_return_release_tls_block_non_head_thread(void* arg) {
20522065
butil::iobuf::release_tls_block(tail);
20532066

20542067
if (tls_block_chain_has_cycle()) {
2055-
*has_cycle = true;
2068+
result->has_cycle = true;
20562069
cleanup_corrupted_tls_chain(3);
20572070
} else {
20582071
butil::iobuf::remove_tls_block_chain();
@@ -2061,33 +2074,38 @@ static void* double_return_release_tls_block_non_head_thread(void* arg) {
20612074
}
20622075

20632076
TEST_F(IOBufTest, regression_3243_release_tls_block_non_head_no_cycle) {
2064-
bool has_cycle = false;
2077+
CycleRegressionResult result = {false, false};
20652078
pthread_t tid;
20662079
ASSERT_EQ(0, pthread_create(&tid, NULL,
20672080
double_return_release_tls_block_non_head_thread,
2068-
&has_cycle));
2081+
&result));
20692082
ASSERT_EQ(0, pthread_join(tid, NULL));
20702083

2071-
EXPECT_FALSE(has_cycle)
2084+
ASSERT_TRUE(result.setup_ok)
2085+
<< "Failed to allocate TLS blocks for regression setup.";
2086+
EXPECT_FALSE(result.has_cycle)
20722087
<< "release_tls_block() created a cycle when a block already present "
20732088
"deeper in the TLS list was returned again. "
20742089
"(GitHub issue #3243)";
20752090
}
20762091

20772092
static void* double_return_release_tls_block_chain_head_thread(void* arg) {
2078-
bool* has_cycle = static_cast<bool*>(arg);
2093+
CycleRegressionResult* result = static_cast<CycleRegressionResult*>(arg);
2094+
result->setup_ok = false;
2095+
result->has_cycle = false;
20792096
butil::iobuf::remove_tls_block_chain();
20802097

20812098
butil::IOBuf::Block* b = butil::iobuf::acquire_tls_block();
20822099
if (!b) {
20832100
return NULL;
20842101
}
2102+
result->setup_ok = true;
20852103
butil::iobuf::release_tls_block(b);
20862104
b->u.portal_next = NULL;
20872105
butil::iobuf::release_tls_block_chain(b);
20882106

20892107
if (tls_block_chain_has_cycle()) {
2090-
*has_cycle = true;
2108+
result->has_cycle = true;
20912109
cleanup_corrupted_tls_chain(2);
20922110
} else {
20932111
butil::iobuf::remove_tls_block_chain();
@@ -2096,20 +2114,24 @@ static void* double_return_release_tls_block_chain_head_thread(void* arg) {
20962114
}
20972115

20982116
TEST_F(IOBufTest, regression_3243_release_tls_block_chain_head_no_cycle) {
2099-
bool has_cycle = false;
2117+
CycleRegressionResult result = {false, false};
21002118
pthread_t tid;
21012119
ASSERT_EQ(0, pthread_create(&tid, NULL,
21022120
double_return_release_tls_block_chain_head_thread,
2103-
&has_cycle));
2121+
&result));
21042122
ASSERT_EQ(0, pthread_join(tid, NULL));
21052123

2106-
EXPECT_FALSE(has_cycle)
2124+
ASSERT_TRUE(result.setup_ok)
2125+
<< "Failed to allocate a TLS block for chain regression setup.";
2126+
EXPECT_FALSE(result.has_cycle)
21072127
<< "release_tls_block_chain() created a cycle when the returned chain "
21082128
"overlapped the TLS head. (GitHub issue #3243)";
21092129
}
21102130

21112131
static void* double_return_release_tls_block_chain_non_head_thread(void* arg) {
2112-
bool* has_cycle = static_cast<bool*>(arg);
2132+
CycleRegressionResult* result = static_cast<CycleRegressionResult*>(arg);
2133+
result->setup_ok = false;
2134+
result->has_cycle = false;
21132135
butil::iobuf::remove_tls_block_chain();
21142136

21152137
butil::IOBuf::Block* tail = butil::iobuf::acquire_tls_block();
@@ -2118,6 +2140,7 @@ static void* double_return_release_tls_block_chain_non_head_thread(void* arg) {
21182140
dec_ref_distinct_blocks(tail, head);
21192141
return NULL;
21202142
}
2143+
result->setup_ok = true;
21212144

21222145
butil::iobuf::release_tls_block(tail);
21232146
butil::iobuf::release_tls_block(head);
@@ -2127,7 +2150,7 @@ static void* double_return_release_tls_block_chain_non_head_thread(void* arg) {
21272150
butil::iobuf::release_tls_block_chain(tail);
21282151

21292152
if (tls_block_chain_has_cycle()) {
2130-
*has_cycle = true;
2153+
result->has_cycle = true;
21312154
cleanup_corrupted_tls_chain(3);
21322155
} else {
21332156
butil::iobuf::remove_tls_block_chain();
@@ -2136,26 +2159,30 @@ static void* double_return_release_tls_block_chain_non_head_thread(void* arg) {
21362159
}
21372160

21382161
TEST_F(IOBufTest, regression_3243_release_tls_block_chain_non_head_no_cycle) {
2139-
bool has_cycle = false;
2162+
CycleRegressionResult result = {false, false};
21402163
pthread_t tid;
21412164
ASSERT_EQ(0, pthread_create(&tid, NULL,
21422165
double_return_release_tls_block_chain_non_head_thread,
2143-
&has_cycle));
2166+
&result));
21442167
ASSERT_EQ(0, pthread_join(tid, NULL));
21452168

2146-
EXPECT_FALSE(has_cycle)
2169+
ASSERT_TRUE(result.setup_ok)
2170+
<< "Failed to allocate TLS blocks for chain regression setup.";
2171+
EXPECT_FALSE(result.has_cycle)
21472172
<< "release_tls_block_chain() created a cycle when the returned chain "
21482173
"contained a block already present deeper in TLS. "
21492174
"(GitHub issue #3243)";
21502175
}
21512176

21522177
struct PartialOverlapResult {
2178+
bool setup_ok;
21532179
bool has_cycle;
21542180
int tls_block_count;
21552181
};
21562182

21572183
static void* partial_overlap_release_tls_block_chain_thread(void* arg) {
21582184
PartialOverlapResult* result = static_cast<PartialOverlapResult*>(arg);
2185+
result->setup_ok = false;
21592186
result->has_cycle = false;
21602187
result->tls_block_count = -1;
21612188
butil::iobuf::remove_tls_block_chain();
@@ -2167,6 +2194,7 @@ static void* partial_overlap_release_tls_block_chain_thread(void* arg) {
21672194
dec_ref_distinct_blocks(tail, head, prefix);
21682195
return NULL;
21692196
}
2197+
result->setup_ok = true;
21702198

21712199
butil::iobuf::release_tls_block(tail);
21722200
butil::iobuf::release_tls_block(head);
@@ -2187,6 +2215,7 @@ static void* partial_overlap_release_tls_block_chain_thread(void* arg) {
21872215

21882216
TEST_F(IOBufTest, regression_3243_release_tls_block_chain_partial_overlap_keeps_prefix) {
21892217
PartialOverlapResult result;
2218+
result.setup_ok = false;
21902219
result.has_cycle = false;
21912220
result.tls_block_count = -1;
21922221

@@ -2196,6 +2225,8 @@ TEST_F(IOBufTest, regression_3243_release_tls_block_chain_partial_overlap_keeps_
21962225
&result));
21972226
ASSERT_EQ(0, pthread_join(tid, NULL));
21982227

2228+
ASSERT_TRUE(result.setup_ok)
2229+
<< "Failed to allocate TLS blocks for partial-overlap regression setup.";
21992230
EXPECT_FALSE(result.has_cycle)
22002231
<< "release_tls_block_chain() created a cycle when a unique prefix "
22012232
"was returned ahead of a block already cached in TLS. "
@@ -2209,40 +2240,49 @@ TEST_F(IOBufTest, regression_3243_release_tls_block_chain_partial_overlap_keeps_
22092240
// eagerly returns _cur_block to TLS. A subsequent release of the same pointer
22102241
// used to create a self-loop at the head.
22112242
static void* backup_double_return_thread(void* arg) {
2212-
bool* has_cycle = static_cast<bool*>(arg);
2243+
CycleRegressionResult* result = static_cast<CycleRegressionResult*>(arg);
2244+
result->setup_ok = false;
2245+
result->has_cycle = false;
22132246
butil::iobuf::remove_tls_block_chain();
22142247

22152248
butil::IOBuf buf;
22162249
{
22172250
butil::IOBufAsZeroCopyOutputStream stream(&buf);
22182251
void* data = NULL;
22192252
int size = 0;
2220-
EXPECT_TRUE(stream.Next(&data, &size));
2253+
if (!stream.Next(&data, &size)) {
2254+
return NULL;
2255+
}
22212256
stream.BackUp(size);
22222257

22232258
butil::IOBuf::Block* head = butil::iobuf::get_tls_block_head();
2224-
EXPECT_TRUE(head != NULL);
2259+
if (head == NULL) {
2260+
return NULL;
2261+
}
2262+
result->setup_ok = true;
22252263
butil::iobuf::release_tls_block(head);
22262264

22272265
if (tls_block_chain_has_cycle()) {
2228-
*has_cycle = true;
2266+
result->has_cycle = true;
22292267
cleanup_corrupted_tls_chain(2);
22302268
}
22312269
}
2232-
if (!*has_cycle) {
2270+
if (!result->has_cycle) {
22332271
butil::iobuf::remove_tls_block_chain();
22342272
}
22352273
return NULL;
22362274
}
22372275

22382276
TEST_F(IOBufTest, regression_3243_backup_then_double_release_no_cycle) {
2239-
bool has_cycle = false;
2277+
CycleRegressionResult result = {false, false};
22402278
pthread_t tid;
22412279
ASSERT_EQ(0, pthread_create(&tid, NULL,
2242-
backup_double_return_thread, &has_cycle));
2280+
backup_double_return_thread, &result));
22432281
ASSERT_EQ(0, pthread_join(tid, NULL));
22442282

2245-
EXPECT_FALSE(has_cycle)
2283+
ASSERT_TRUE(result.setup_ok)
2284+
<< "Failed to set up IOBufAsZeroCopyOutputStream regression path.";
2285+
EXPECT_FALSE(result.has_cycle)
22462286
<< "After IOBufAsZeroCopyOutputStream::BackUp() returned a block to "
22472287
"TLS, a second release_tls_block() created a cycle. "
22482288
"(GitHub issue #3243)";

0 commit comments

Comments
 (0)