diff --git a/src/torrent/utils/thread_interrupt.cc b/src/torrent/utils/thread_interrupt.cc index 4c23fb764..b8cb73f6f 100644 --- a/src/torrent/utils/thread_interrupt.cc +++ b/src/torrent/utils/thread_interrupt.cc @@ -27,7 +27,8 @@ thread_interrupt::~thread_interrupt() { bool thread_interrupt::poke() { - if (m_poking.test_and_set()) + bool expected = false; + if (!m_other->m_poking.compare_exchange_strong(expected, true)) return true; int result = ::send(m_fileDesc, "a", 1, 0); @@ -61,10 +62,6 @@ thread_interrupt::create_pair() { void thread_interrupt::event_read() { - // This has a race condition where if poked again while processing the polled events it might be - // missed. - m_poking.clear(); - char buffer[256]; int result = ::recv(m_fileDesc, buffer, 256, 0); @@ -73,6 +70,8 @@ thread_interrupt::event_read() { throw internal_error("Invalid result reading from thread_interrupt socket."); instrumentation_update(INSTRUMENTATION_POLLING_INTERRUPT_READ_EVENT, 1); + + m_poking = false; } } diff --git a/src/torrent/utils/thread_interrupt.h b/src/torrent/utils/thread_interrupt.h index 025143b9c..02b0eccc4 100644 --- a/src/torrent/utils/thread_interrupt.h +++ b/src/torrent/utils/thread_interrupt.h @@ -30,7 +30,7 @@ class LIBTORRENT_EXPORT thread_interrupt : public Event { SocketFd& get_fd() { return *reinterpret_cast(&m_fileDesc); } thread_interrupt* m_other; - std::atomic_flag m_poking; + std::atomic_bool m_poking; }; } diff --git a/test/helpers/test_thread.h b/test/helpers/test_thread.h index 82869cb45..7c3dfe1d8 100644 --- a/test/helpers/test_thread.h +++ b/test/helpers/test_thread.h @@ -33,7 +33,7 @@ class test_thread : public torrent::thread_base { void init_thread(); - void set_pre_stop() { m_test_state |= test_flag_pre_stop; } + void set_pre_stop() { m_test_flags |= test_flag_pre_stop; } void set_acquire_global() { m_test_flags |= test_flag_acquire_global; } void set_test_flag(int flags) { m_test_flags |= flags; }