This question already has an answer here:
Is there a bug in the boost asio HTTP Server 3 example or boost bug?
(1 answer)
Closed 9 years ago.
i am trying to write a program with boost::asio and multiple threads. The program seems to be working fine, but when i run it with the valgrind thread tool drd, I get messages of conflicting store and load operations.
==13740== Thread 2:
==13740== Conflicting store by thread 2 at 0x06265ff0 size 4
==13740== at 0x40F2B8: boost::asio::detail::epoll_reactor::descriptor_state::set_ready_events(unsigned int) (epoll_reactor.hpp:68)
==13740== by 0x410097: boost::asio::detail::epoll_reactor::run(bool, boost::asio::detail::op_queue&) (epoll_reactor.ipp:430)
etc.
The error messages are rather lengthy due to all the involved boost calls and seem not to include my functions directly. As I said, the program seems to work, but leaving these errors inside the code leaves me with a bad feeling. Is there any good way, to find the problematic locations in the code?
Thanks for the advice
A related bug report landed in Ubuntu's bug trackers (not the right place IYAM):
https://bugs.launchpad.net/ubuntu/+source/boost1.53/+bug/1243570
This details a lock order violation detected with Helgrind (not DRD). This is more tangible
Some old but perhaps interesting discussion about this here: http://lists.boost.org/Archives/boost/2010/06/167818.php
My comments on this source code are as follows:
The comments at the bottom of class epoll_reactor say that any
access of registered_descriptors_ should be protected by
registered_descriptors_mutex_. However, the method shutdown_service()
modifies the container registered_descriptors_ but doesn't lock
registered_descriptors_mutex_.
The method epoll_reactor::register_descriptor() modifies its second
argument (descriptor_data) such that it points to the newly created
descriptor_state object. All data members of the struct
descriptor_state are public, but all accesses must be guarded by a
lock on descriptor_state::mutex_. So all callers of
register_descriptor() must be checked in order to verify whether or
not there are any thread-unsafe accesses of
descriptor_state::op_queue_ or descriptor_state::shutdown_. Personally
I never recommended such a class design.
While all accesses of the members of struct descriptor_state should
be protected by locking descriptor_state::mutex_, no lock is held on
this last mutex by register_descriptor() when it sets
descriptor_data::shutdown_ nor by shutdown_service() while it modifies
descriptor_state::op_queue_ and descriptor_state::shutdown_. The
former is easy to fix: move the "descriptor_data->shutdown_ = false"
statement to somewhere before the epoll_ctl() system call.
Does one of the above scenarios explain the race report you have observed ?
Of course, many version passed since then (1.43.0-1.55.0) so chances are this has been addressed, or otherwise changed, but it could give you a lead to find more information in the boost trackers?
Related
This question already has answers here:
What happens if two threads read & write the same piece of memory
(3 answers)
Closed 2 years ago.
What happens when in one thread write and in second thread read the same object? It would lead to application crash?
My idea is, on main thread save the data in to object or change the data from object and on second thread only read this data.
If I understand, the problem can be only while writing to object new value and reading in same time from same object, reading value will be old. But this is not problem for me.
I search my question and found this topic What happens if two threads read & write the same piece of memory but I am not sure if it apply for my question.
Unless the object is atomic, the behaviour of one thread writing and another thread reading the same object is undefined.
Your current perception that the only issue is that state data could be read is not correct. You cannot assume that will be only manifestation of the undefined behaviour. In particular, you may well find that the value you read is neither the old nor the new value.
It really depends on the size of the memory block you are trying to read and write from. If you are reading a single atomic data type then you can only read and write to the memory block as a whole (int as an example). You'll either non-deterministic-ally get the new or old value from the data type without any issues.
If you are reading and writing to a block of memory that isn't atomic, then during the reading cycle, some of the blocks can be overwritten and as such, the information can be corrupted. This will lead to some wild behavior and may cause breaks.
https://en.wikipedia.org/wiki/Linearizability
It is not safe. Consider using mutex to avoid memory corruption :
http://en.cppreference.com/w/cpp/thread/mutex
Generally the result is simply undefined. You have to do things to make it defined and you have a lot of docs to read.
The compiler has to know that values might be changed from under it. Otherwise the optimizer will do the wrong thing and writes can be completely ignored. The keyword here is volatile. This is required when variables are changed from signal handlers or by the hardware itself. Not sufficient for multithreading.
You must ensure that reads and writes are not interrupted. One way to do this is to use atomic types. The other is to protect access to a variable using locks or mutexes. Atomic types are limited in size by what the hardware supports so anything beyond simple integers or single pointers will require locks. The std::atomic type abstracts this away. It knows which types are atomic on your hardware and when it needs to use locking.
Even that isn't enough since the timing of reads and writes is still random. If one thread writes and the other reads what will it read? Will the second thread read just before the first writes or just after? Even with all the right use of atomic or locks you don't know weather you will get the old or new value. If that matters you have to synchronize between the threads so the order of reads and writes becomes defined. Look for conditions.
I have a situation where I'm having to use a blackboxed wrapper for multithreading (which I suspect sits on top of a TBB Thread Pool).
I have a value that can only be obtained by an object that has an expensive constructor, and each thread needs a local instance of that, which is OK.
That object will produce a value that is guaranteed always identical across threads (all constructors take the same const forming argument from the main loop).
Each thread also has access to a shared struct for that argument as well as to save some results.
The value in question (an iteration range in the form of unsigned int) required by the threads is used later in the main loop, so if I could I'd rather not create another expensive instance of the above mentioned object just to get that same value again.
My question is, on Windows with VC11, and Linux with GCC 4.8.2, on x86-64, is writing the same value to the same memory location (int in a struct the threads have a pointer to) from multiple threads a benign race? Is it a race I could just let happen without guarding the value with an expensive lock? From cursory testing it seems to be the case, but I'm not entirely sure whether under the hood the operation is atomic and safe, or if there's a potential for corruption that might show up under stress.
If the data race is "benign" or not really depends on the compiler and runtime platform. Compilers assume programs are race-free and and behaviour resulting from race conditions is undefined. Using atomic operations does not incur much overhead and is recommended in this situation.
Some fringe cases and very good examples on what could go wrong can be found here:
https://software.intel.com/en-us/blogs/2013/01/06/benign-data-races-what-could-possibly-go-wrong
In his post ThreadSanitizer developer Dmitry Vyukov writes "So, if a data race involves non-atomic writes, it always can go wrong".
I have a Singleton application server (assume being created correctly). The server class has a non static vector member which is modified in several methods. Is it possible that the compiler optimizes the code such that the vector is modified non serially across several request processing method chains. I mean can two chains of method calls may intersect across different requests ?
I think they can because the method calls would be jumps to labels .
Ok seeing your comments I'm posting an answer because something needs to be clear : std containers are not "threadsafe".
They provide some protection and garantees, like the fact that you can have multiple readers safely.
However you cannot have multiple writers, or writers and readers concurrently.
Regarding your question : the compiler is not guilty.
Given your comment I suppose you have conccurent writes and reads on your std::vector which is where you have a problem right now.
Just add a mutex, and check if the performance isn't too horrid. If it is look for another datastructure/architecture.
I am well aware that similar questions have been asked before and I'm also aware, that the operation is most likely not atomic at all, but I'm still asking out of idle curiosity and in hope that there's some way to MAKE it atomic.
The situation: Inside a struct, there's an unsigned char variable called Busy. (It can be moved out of there and stand on its own though).
This variable Busy is modified by two concurrent threads, one who sets bits on scheduling and one who clears them upon completion of the scheduled action.
Right now, the scheduling looks like this:
while(SEC.Busy&(1 << SEC.ReqID))
if(++SEC.ReqID == 5) SEC.ReqID = 0;
sQuery.cData[2] = SEC.ReqID;
while the clearing of the bitmaks looks like this:
SEC.Busy &= ~(1 << sQuery->cData[2]);
cData[2] basically carries the information about which slot is used over the network and comes back via a callback in another thread.
Now the question: How can I make sure that SEC.Busy (which is the only variable in this troubled situation) doesn't get torn apart by two threads trying to alter it at the same time without using a mutex, critical section or anything of the likes if possible?
I've also tried assigning the content of SEC.Busy to a local variable, alter that and then write the variable back, but unfortunately this operation also doesn't seem atomic.
I'm using Borland C++ Builder 6 at the moment, though a GCC solution would also be just fine.
Thank you very much.
C++03 (nor C99) does not say anything about atomicity at all. Assignment is atomic (= everybody sees either the old or the new value) on most platforms, but because it is not synchronized (= anybody may see the old value after they saw new value for other updates) on any, it is useless anyway. Any other operation like increment, set bit and such is likely not even atomic.
C++11 defines std::atomic template, which ensures both atomicity and synchronization, so you need to use it. Boost provides compatible implementation for most C++03 compilers and gcc has had built-in support since 4.2, which is being replaced by more advanced support needed by C++11 in gcc 4.7
Windows API had "Interlocked operations" since long ago. Unix alternative required assembly (which several libraries provided) before introduction of the gcc __sync function.
There are three potential problems when accessing shared data from multiple threads. First, you might get a thread switch in the middle of a memory access that requires more than one bus cycle; this is called "tearing". Second, each processor has its own memory cache, and writing data to one cache does not automatically write to other caches, so a different thread can see stale data. Third, the compiler can move instructions around, so that another processor might see a later store to one variable without seeing a preceding store to another one.
Using a variable of type unsigned char almost certainly removes the first one, but it doesn't have any effect on the other two.
To avoid all three problems, use atomic<unsigned char> from C++11 or whatever synchronizing techniques your compiler and OS provide.
I have one std::list<> container and these threads:
One writer thread which adds elements indefinitely.
One reader/writer thread which reads and removes elements while available.
Several reader threads which access the SIZE of the container (by using the size() method)
There is a normal mutex which protects the access to the list from the first two threads. My question is, do the size reader threads need to acquire this mutex too? should I use a read/write mutex?
I'm in a windows environment using Visual C++ 6.
Update: It looks like the answer is not clear yet. To sum up the main doubt: Do I still need to protect the SIZE reader threads even if they only call size() (which returns a simple variable) taking into account that I don't need the exact value (i.e. I can assume a +/- 1 variation)? How a race condition could make my size() call return an invalid value (i.e. one totally unrelated to the good one)?
Answer: In general, the reader threads must be protected to avoid race conditions. Nevertheless, in my opinion, some of the questions stated above in the update haven't been answered yet.
Thanks in advance!
Thank you all for your answers!
Yes, the read threads will need some sort of mutex control, otherwise the write will change things from under it.
A reader/writer mutex should be enough. But strictly speaking this is an implmentation-specific issue. It's possible that an implementation may have mutable members even in const objects that are read-only in your code.
Checkout the concurrent containers provided by Intel's Open Source Threading Building Blocks library. Look under "Container Snippets" on the Code Samples page for some examples. They have concurrent / thread-safe containers for vectors, hash maps and queues.
I don't believe the STL containers are thread-safe, as there isn't a good way to handle threads cross-platform. The call to size() is simple, but it still needs to be protected.
This sounds like a great place to use read-write locks.
You should consider some SLT implementation might calculate the size when called.
To overcome this, you could define a new variable
volatile unsigned int ContainerSize = 0;
Update the variable only inside already protected update calls, but you can read / test the variable without protection (taking into account you don't need the exact value).
Yes. I would suggest wrapping your STL library with a class that enforces serial access. Or find a similar class that's already been debugged.
I'm going to say no. In this case.
Without a mutex, what you might find is that the size() returns the wrong value occasionally, as items are added or removed. If this is acceptable to you, go for it.
however, if you need the accurate size of the list when the reader needs to know it, you'll have to put a critical section around every size call in addition to the one you have around the add and erase calls.
PS. VC6 size() simply returns the _Size internal member, so not having a mutex won't be a problem with your particular implementation, except that it might return 1 when a second element is being added, or vice-versa.
PPS. someone mentioned a RW lock, this is a good thing, especially if you're tempted to access the list objects later. Change your mutex to a Boost::shared_mutex would be beneficial then. However no mutex whatsoever is needed if all you're calling is size().
The STL in VC++ version 6 is not thread-safe, see this recent question. So it seems your question is a bit irrelevant. Even if you did everything right, you may still have problems.
Whether or not size() is safe (for the definition of "safe" that you provide) is implementation-dependent. Even if you are covered on your platform, for your version of your compiler at your optimization level for your version of thread library and C runtime, please do not code this way. It will come back to byte you, and it will be hell to debug. You're setting yourself up for failure.