Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions cmd/examples/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1172,9 +1172,6 @@ main(int argc, char* argv[])
// Install a signal handlers to catch operating system signals
installSignalHandlers();

// Lock the mutex so that main can then wait on it
std::unique_lock lock(moq_example::main_mutex);

bool enable_pub{ false };
bool enable_sub{ false };
bool enable_fetch{ false };
Expand All @@ -1190,14 +1187,17 @@ main(int argc, char* argv[])
exit(-1);
}

while (not stop_threads) {
while (not stop_threads && not moq_example::terminate.load()) {
if (client->GetStatus() == MyClient::Status::kReady) {
Comment on lines 1189 to 1191

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Synchronize terminate flag read during connect loop

In the connect loop, moq_example::terminate is now read without holding main_mutex, but the signal handler writes it under that mutex (signal_handler.h). If a SIGINT arrives while this loop is running, the handler can write concurrently with this unsynchronized read, which is a data race/UB and can cause missed termination or undefined behavior. Consider making terminate an std::atomic<bool> or taking the same mutex when reading it here.

Useful? React with 👍 / 👎.

SPDLOG_INFO("Connected to server");
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}

// Lock the mutex for cv.wait
std::unique_lock lock(moq_example::main_mutex);

std::thread pub_thread;
std::thread sub_thread;
std::thread fetch_thread;
Expand Down Expand Up @@ -1258,7 +1258,7 @@ main(int argc, char* argv[])
}

// Wait until told to terminate
moq_example::cv.wait(lock, [&]() { return moq_example::terminate; });
moq_example::cv.wait(lock, [&]() { return moq_example::terminate.load(); });

stop_threads = true;
SPDLOG_INFO("Stopping threads...");
Expand Down
2 changes: 1 addition & 1 deletion cmd/examples/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1065,7 +1065,7 @@ main(int argc, char* argv[])
}

// Wait until told to terminate
moq_example::cv.wait(lock, [&]() { return moq_example::terminate; });
moq_example::cv.wait(lock, [&]() { return moq_example::terminate.load(); });

// Unlock the mutex
lock.unlock();
Expand Down
3 changes: 2 additions & 1 deletion cmd/examples/signal_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@

#pragma once

#include <atomic>
#include <condition_variable>
#include <csignal>
#include <iostream>
#include <mutex>

namespace moq_example {
std::mutex main_mutex; // Main's mutex
bool terminate{ false }; // Termination flag
std::atomic<bool> terminate{ false }; // Termination flag
std::condition_variable cv; // Main thread waits on this
const char* termination_reason{ nullptr }; // Termination reason
};
Expand Down
3 changes: 3 additions & 0 deletions src/transport_picoquic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2628,6 +2628,9 @@ PicoQuicTransport::Shutdown()

if (quic_network_thread_ctx_ != NULL) {
SPDLOG_LOGGER_INFO(logger, "Closing transport picoquic thread");

// Signal thread to exit BEFORE waiting
quic_network_thread_ctx_->thread_should_close = 1;
picoquic_wake_up_network_thread(quic_network_thread_ctx_);

while (quic_network_thread_ctx_->thread_is_ready) {
Expand Down