Skip to content

Commit 94b98f1

Browse files
committed
Fix lifetime sanitizer false positive for PABotBase's retransmit thread.
1 parent bed00d2 commit 94b98f1

File tree

3 files changed

+44
-37
lines changed

3 files changed

+44
-37
lines changed

ClientSource/Connection/PABotBase.cpp

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,16 @@ PABotBase::PABotBase(
4545
, m_last_ack(current_time())
4646
, m_state(State::RUNNING)
4747
, m_error(false)
48-
, m_retransmit_thread(run_with_catch, "PABotBase::retransmit_thread()", [this]{ retransmit_thread(); })
4948
{
5049
set_sniffer(message_logger);
50+
51+
// We must initialize this last because it will trigger the lifetime
52+
// sanitizer if it beats it to construction.
53+
m_retransmit_thread = std::thread(
54+
run_with_catch,
55+
"PABotBase::retransmit_thread()",
56+
[this]{ retransmit_thread(); }
57+
);
5158
}
5259
PABotBase::~PABotBase(){
5360
stop();
@@ -57,7 +64,7 @@ PABotBase::~PABotBase(){
5764
}
5865

5966
size_t PABotBase::inflight_requests(){
60-
m_sanitizer.check_usage();
67+
auto scope_check = m_sanitizer.check_scope();
6168

6269
// Must be called under m_state_lock.
6370

@@ -71,15 +78,15 @@ size_t PABotBase::inflight_requests(){
7178
}
7279

7380
void PABotBase::connect(){
74-
m_sanitizer.check_usage();
81+
auto scope_check = m_sanitizer.check_scope();
7582

7683
pabb_MsgAckRequest response;
7784
issue_request_and_wait(
7885
Microcontroller::DeviceRequest_seqnum_reset(), nullptr
7986
).convert<PABB_MSG_ACK_REQUEST>(logger(), response);
8087
}
8188
void PABotBase::stop(){
82-
m_sanitizer.check_usage();
89+
auto scope_check = m_sanitizer.check_scope();
8390

8491
// Make sure only one thread can get in here.
8592
State expected = State::RUNNING;
@@ -95,7 +102,7 @@ void PABotBase::stop(){
95102
m_retransmit_thread.join();
96103

97104
{
98-
SpinLockGuard lg(m_state_lock, "PABotBase::stop()");
105+
ReadSpinLock lg(m_state_lock, "PABotBase::stop()");
99106

100107
// Send a stop request, but don't wait for a response that we may never
101108
// receive.
@@ -122,7 +129,7 @@ void PABotBase::set_queue_limit(size_t queue_limit){
122129
}
123130

124131
void PABotBase::wait_for_all_requests(const Cancellable* cancelled){
125-
m_sanitizer.check_usage();
132+
auto scope_check = m_sanitizer.check_scope();
126133

127134
std::unique_lock<std::mutex> lg(m_sleep_lock);
128135
m_logger.log("Waiting for all requests to finish...", COLOR_DARKGREEN);
@@ -134,7 +141,7 @@ void PABotBase::wait_for_all_requests(const Cancellable* cancelled){
134141
throw InvalidConnectionStateException();
135142
}
136143
{
137-
SpinLockGuard lg1(m_state_lock, "PABotBase::wait_for_all_requests()");
144+
ReadSpinLock lg1(m_state_lock, "PABotBase::wait_for_all_requests()");
138145
#if 0
139146
m_logger.log(
140147
"Waiting for all requests to finish... (Requests: " +
@@ -170,7 +177,7 @@ bool PABotBase::try_stop_all_commands(){
170177
cout << "-----------------------------------------------------------------------------------------" << endl;
171178
#endif
172179

173-
m_sanitizer.check_usage();
180+
auto scope_check = m_sanitizer.check_scope();
174181

175182
uint64_t seqnum = try_issue_request(nullptr, Microcontroller::DeviceRequest_request_stop(), true);
176183
if (seqnum != 0){
@@ -197,13 +204,13 @@ void PABotBase::stop_all_commands(){
197204
cout << "-----------------------------------------------------------------------------------------" << endl;
198205
#endif
199206

200-
m_sanitizer.check_usage();
207+
auto scope_check = m_sanitizer.check_scope();
201208

202209
uint64_t seqnum = issue_request(nullptr, Microcontroller::DeviceRequest_request_stop(), true);
203210
clear_all_active_commands(seqnum);
204211
}
205212
bool PABotBase::try_next_command_interrupt(){
206-
m_sanitizer.check_usage();
213+
auto scope_check = m_sanitizer.check_scope();
207214

208215
uint64_t seqnum = try_issue_request(nullptr, Microcontroller::DeviceRequest_next_command_interrupt(), true);
209216
if (seqnum != 0){
@@ -214,17 +221,17 @@ bool PABotBase::try_next_command_interrupt(){
214221
}
215222
}
216223
void PABotBase::next_command_interrupt(){
217-
m_sanitizer.check_usage();
224+
auto scope_check = m_sanitizer.check_scope();
218225

219226
uint64_t seqnum = issue_request(nullptr, Microcontroller::DeviceRequest_next_command_interrupt(), true);
220227
clear_all_active_commands(seqnum);
221228
}
222229
void PABotBase::clear_all_active_commands(uint64_t seqnum){
223-
m_sanitizer.check_usage();
230+
auto scope_check = m_sanitizer.check_scope();
224231

225232
// Remove all commands at or before the specified seqnum.
226233
std::lock_guard<std::mutex> lg0(m_sleep_lock);
227-
SpinLockGuard lg1(m_state_lock, "PABotBase::next_command_interrupt()");
234+
WriteSpinLock lg1(m_state_lock, "PABotBase::next_command_interrupt()");
228235
m_logger.log("Clearing all active commands... (Commands: " + std::to_string(m_pending_commands.size()) + ")", COLOR_DARKGREEN);
229236

230237
// if (m_pending_commands.size() > 2){
@@ -247,7 +254,7 @@ void PABotBase::clear_all_active_commands(uint64_t seqnum){
247254
}
248255
template <typename Map>
249256
uint64_t PABotBase::infer_full_seqnum(const Map& map, seqnum_t seqnum) const{
250-
m_sanitizer.check_usage();
257+
auto scope_check = m_sanitizer.check_scope();
251258

252259
// The protocol uses a 32-bit seqnum that wraps around. For our purposes of
253260
// retransmits, we use a full 64-bit seqnum to maintain sorting order
@@ -274,7 +281,7 @@ uint64_t PABotBase::infer_full_seqnum(const Map& map, seqnum_t seqnum) const{
274281
}
275282

276283
uint64_t PABotBase::oldest_live_seqnum() const{
277-
m_sanitizer.check_usage();
284+
auto scope_check = m_sanitizer.check_scope();
278285

279286
// Must call under state lock.
280287
uint64_t oldest = m_send_seq;
@@ -289,7 +296,7 @@ uint64_t PABotBase::oldest_live_seqnum() const{
289296

290297
template <typename Params>
291298
void PABotBase::process_ack_request(BotBaseMessage message){
292-
m_sanitizer.check_usage();
299+
auto scope_check = m_sanitizer.check_scope();
293300

294301
if (message.body.size() != sizeof(Params)){
295302
m_sniffer->log("Ignoring message with invalid size.");
@@ -300,7 +307,7 @@ void PABotBase::process_ack_request(BotBaseMessage message){
300307

301308
AckState state;
302309
{
303-
SpinLockGuard lg(m_state_lock, "PABotBase::process_ack_request()");
310+
WriteSpinLock lg(m_state_lock, "PABotBase::process_ack_request()");
304311

305312
if (m_pending_requests.empty()){
306313
m_sniffer->log("Unexpected request ack message: seqnum = " + std::to_string(seqnum));
@@ -345,7 +352,7 @@ void PABotBase::process_ack_request(BotBaseMessage message){
345352
}
346353
template <typename Params>
347354
void PABotBase::process_ack_command(BotBaseMessage message){
348-
m_sanitizer.check_usage();
355+
auto scope_check = m_sanitizer.check_scope();
349356

350357
if (message.body.size() != sizeof(Params)){
351358
m_sniffer->log("Ignoring message with invalid size.");
@@ -354,7 +361,7 @@ void PABotBase::process_ack_command(BotBaseMessage message){
354361
const Params* params = (const Params*)message.body.c_str();
355362
seqnum_t seqnum = params->seqnum;
356363

357-
SpinLockGuard lg(m_state_lock, "PABotBase::process_ack_command()");
364+
WriteSpinLock lg(m_state_lock, "PABotBase::process_ack_command()");
358365

359366
if (m_pending_commands.empty()){
360367
m_sniffer->log("Unexpected command ack message: seqnum = " + std::to_string(seqnum));
@@ -387,7 +394,7 @@ void PABotBase::process_ack_command(BotBaseMessage message){
387394
}
388395
template <typename Params>
389396
void PABotBase::process_command_finished(BotBaseMessage message){
390-
m_sanitizer.check_usage();
397+
auto scope_check = m_sanitizer.check_scope();
391398

392399
if (message.body.size() != sizeof(Params)){
393400
m_sniffer->log("Ignoring message with invalid size.");
@@ -403,7 +410,7 @@ void PABotBase::process_command_finished(BotBaseMessage message){
403410
// m_send_queue.emplace_back((uint8_t)PABB_MSG_ACK, std::string((char*)&ack, sizeof(ack)));
404411

405412
std::lock_guard<std::mutex> lg0(m_sleep_lock);
406-
SpinLockGuard lg1(m_state_lock, "PABotBase::process_command_finished() - 0");
413+
WriteSpinLock lg1(m_state_lock, "PABotBase::process_command_finished() - 0");
407414

408415
send_message(BotBaseMessage(PABB_MSG_ACK_REQUEST, std::string((char*)&ack, sizeof(ack))), false);
409416

@@ -442,7 +449,7 @@ void PABotBase::process_command_finished(BotBaseMessage message){
442449
}
443450
}
444451
void PABotBase::on_recv_message(BotBaseMessage message){
445-
m_sanitizer.check_usage();
452+
auto scope_check = m_sanitizer.check_scope();
446453

447454
switch (message.type){
448455
case PABB_MSG_ACK_COMMAND:
@@ -495,7 +502,7 @@ void PABotBase::on_recv_message(BotBaseMessage message){
495502
}
496503

497504
void PABotBase::retransmit_thread(){
498-
m_sanitizer.check_usage();
505+
auto scope_check = m_sanitizer.check_scope();
499506

500507
// cout << "retransmit_thread()" << endl;
501508
auto last_sent = current_time();
@@ -515,7 +522,7 @@ void PABotBase::retransmit_thread(){
515522
}
516523

517524
// Process retransmits.
518-
SpinLockGuard lg(m_state_lock, "PABotBase::retransmit_thread()");
525+
WriteSpinLock lg(m_state_lock, "PABotBase::retransmit_thread()");
519526
// std::cout << "retransmit_thread - m_pending_messages.size(): " << m_pending_messages.size() << std::endl;
520527
// cout << "m_pending_messages.size()" << endl;
521528

@@ -550,7 +557,7 @@ uint64_t PABotBase::try_issue_request(
550557
const Cancellable* cancelled,
551558
const BotBaseRequest& request, bool silent_remove
552559
){
553-
m_sanitizer.check_usage();
560+
auto scope_check = m_sanitizer.check_scope();
554561

555562
BotBaseMessage message = request.message();
556563
if (message.body.size() < sizeof(uint32_t)){
@@ -560,7 +567,7 @@ uint64_t PABotBase::try_issue_request(
560567
throw InternalProgramError(&m_logger, PA_CURRENT_FUNCTION, "Message is too long.");
561568
}
562569

563-
SpinLockGuard lg(m_state_lock, "PABotBase::try_issue_request()");
570+
WriteSpinLock lg(m_state_lock, "PABotBase::try_issue_request()");
564571
if (cancelled != nullptr && cancelled->cancelled()){
565572
throw OperationCancelledException();
566573
}
@@ -615,7 +622,7 @@ uint64_t PABotBase::try_issue_command(
615622
const Cancellable* cancelled,
616623
const BotBaseRequest& request, bool silent_remove
617624
){
618-
m_sanitizer.check_usage();
625+
auto scope_check = m_sanitizer.check_scope();
619626

620627
BotBaseMessage message = request.message();
621628
if (message.body.size() < sizeof(uint32_t)){
@@ -625,7 +632,7 @@ uint64_t PABotBase::try_issue_command(
625632
throw InternalProgramError(&m_logger, PA_CURRENT_FUNCTION, "Message is too long.");
626633
}
627634

628-
SpinLockGuard lg(m_state_lock, "PABotBase::try_issue_command()");
635+
WriteSpinLock lg(m_state_lock, "PABotBase::try_issue_command()");
629636
if (cancelled != nullptr && cancelled->cancelled()){
630637
throw OperationCancelledException();
631638
}
@@ -686,7 +693,7 @@ uint64_t PABotBase::issue_request(
686693
const Cancellable* cancelled,
687694
const BotBaseRequest& request, bool silent_remove
688695
){
689-
m_sanitizer.check_usage();
696+
auto scope_check = m_sanitizer.check_scope();
690697

691698
// Issue a request or a command and return.
692699
//
@@ -728,7 +735,7 @@ uint64_t PABotBase::issue_command(
728735
const Cancellable* cancelled,
729736
const BotBaseRequest& request, bool silent_remove
730737
){
731-
m_sanitizer.check_usage();
738+
auto scope_check = m_sanitizer.check_scope();
732739

733740
// Issue a request or a command and return.
734741
//
@@ -771,7 +778,7 @@ bool PABotBase::try_issue_request(
771778
const BotBaseRequest& request,
772779
const Cancellable* cancelled
773780
){
774-
m_sanitizer.check_usage();
781+
auto scope_check = m_sanitizer.check_scope();
775782

776783
if (!request.is_command()){
777784
return try_issue_request(cancelled, request, true) != 0;
@@ -783,7 +790,7 @@ void PABotBase::issue_request(
783790
const BotBaseRequest& request,
784791
const Cancellable* cancelled
785792
){
786-
m_sanitizer.check_usage();
793+
auto scope_check = m_sanitizer.check_scope();
787794

788795
if (!request.is_command()){
789796
issue_request(cancelled, request, true);
@@ -796,7 +803,7 @@ BotBaseMessage PABotBase::issue_request_and_wait(
796803
const BotBaseRequest& request,
797804
const Cancellable* cancelled
798805
){
799-
m_sanitizer.check_usage();
806+
auto scope_check = m_sanitizer.check_scope();
800807

801808
if (request.is_command()){
802809
throw InternalProgramError(&m_logger, PA_CURRENT_FUNCTION, "This function only supports requests.");
@@ -806,12 +813,12 @@ BotBaseMessage PABotBase::issue_request_and_wait(
806813
return wait_for_request(seqnum);
807814
}
808815
BotBaseMessage PABotBase::wait_for_request(uint64_t seqnum){
809-
m_sanitizer.check_usage();
816+
auto scope_check = m_sanitizer.check_scope();
810817

811818
std::unique_lock<std::mutex> lg(m_sleep_lock);
812819
while (true){
813820
{
814-
SpinLockGuard slg(m_state_lock, "PABotBase::issue_request_and_wait()");
821+
WriteSpinLock slg(m_state_lock, "PABotBase::issue_request_and_wait()");
815822
auto iter = m_pending_requests.find(seqnum);
816823
if (iter == m_pending_requests.end()){
817824
throw OperationCancelledException();

ClientSource/Connection/SerialConnectionPOSIX.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class SerialConnection : public StreamConnection{
141141

142142
private:
143143
virtual void send(const void* data, size_t bytes){
144-
SpinLockGuard lg(m_send_lock, "SerialConnection::send()");
144+
WriteSpinLock lg(m_send_lock, "SerialConnection::send()");
145145
bytes = write(m_fd, data, bytes);
146146
}
147147

ClientSource/Connection/SerialConnectionWinAPI.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class SerialConnection : public StreamConnection{
129129

130130

131131
virtual void send(const void* data, size_t bytes){
132-
SpinLockGuard lg(m_send_lock, "SerialConnection::send()");
132+
WriteSpinLock lg(m_send_lock, "SerialConnection::send()");
133133
#if 0
134134
for (size_t c = 0; c < bytes; c++){
135135
std::cout << "Send: " << (int)((const char*)data)[c] << std::endl;

0 commit comments

Comments
 (0)