-
Notifications
You must be signed in to change notification settings - Fork 93
Description
Issue Summary
When using boost::lockfree::queue<T> with T as a pointer type (e.g., PGconn*), concurrent pop() operations may return the same front node to multiple threads, even if the return value is checked. This violates the queue's thread-safety guarantee.
Reproduction Steps
- Define a queue with pointer type (e.g.,
PGconn*pointers):boost::lockfree::queue<PGconn*> unsafe_queue(1024); - Concurrently call
push()andpop()from multiple threads and track the number of times eachPGconn*is popped and pushed.
Expected Behavior
Each enqueued PGconn* should be pushed and popped equal times.
Actual Behavior
For boost::lockfree::queue<PGconn*>, some PGconn* pointers are popped much more times than they are pushed.
For boost::lockfree::queue<Conn> (where Conn wraps PGconn*), the behavior is correct (pop count == push count).
Example Code
// Thread-unsafe case
boost::lockfree::queue<PGconn*> unsafe_queue(1024);
// Concurrent pushes and pops will yield duplicate PGconn* pointers.
// Thread-safe case
struct Conn { PGconn* pgconn; };
boost::lockfree::queue<Conn> safe_queue(1024);
// Concurrent pushes and pops behave correctly.Root Cause Analysis
The issue likely stems from how pointer types are handled internally in boost::lockfree::queue. The queue may fail to atomically update the head node when T is a pointer, leading to race conditions. This does not occur when T is a user-defined type (e.g., Conn), possibly due to stricter memory ordering or type-specific handling.
Every time an element is dequeued, its number of entries and exits is counted once. The number of pops is always greater than or equal to pushes. There has never been a situation where the number of pops is less than pushes. Therefore, the problem is likely to lie in the pop().
Environment
Boost version: 1.83.0
Compiler: gcc/g++ 13.3
OS: Linux x86_64
Additional Notes
The bug may also affect other pointer types (int*, custom class pointers, etc.), but only PGconn* is explicitly tested.
The lock-free context used for push() and pop() operations is confirmed to be correct (no external races).