@@ -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+
20042009static 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
20242032TEST_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
20372047static 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
20632076TEST_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
20772092static 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
20982116TEST_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
21112131static 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
21382161TEST_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
21522177struct PartialOverlapResult {
2178+ bool setup_ok;
21532179 bool has_cycle;
21542180 int tls_block_count;
21552181};
21562182
21572183static 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
21882216TEST_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.
22112242static 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
22382276TEST_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