-
Notifications
You must be signed in to change notification settings - Fork 212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Synchronization on shutdown. #13
Comments
I don't think that this is sufficient. The wait predicate AFAIK is to guard against spurious wakeup. It's probably recommended, but I don't think that it solves the race condition. Your call operator should look more like this:
The problem described is then fixed by locking the mutex in your
Similarly, in
|
@yvoinov In the case of |
After a lot of testing, I'm using quite different thread pool implementation: https://github.com/yvoinov/thread-pool-cpp There is no race condition on submit. Without lock notify_*. This implementation works perfectly, no deadlocks, no races. To prevent lost wakeup it is enough to lock conditional variable mutex during notify_one(). It described here: http://www.modernescpp.com/index.php/c-core-guidelines-be-aware-of-the-traps-of-condition-variables |
I have noticed that there seems to be a race condition in the shutdown process of ThreadPool. By example let Thread1 be the main thread executing
shutdown()
and let Thread2 be a ThreadWorker executing operator(). If we take the following interleaving of calls (assuming that the queue is empty by the start):Thread2: checks the while condition and returns true.
Thread1: sets m_shutdown to false.
Thread1: calls m_conditional_lock.notify_all().
Thread2: takes ownership of m_pool->m_conditional_mutex.
Thread2: call m_pool->m_conditional_lock.wait( lock ).
In the above scenario it can be seen that the notify_all() is completed before Thread2 calls wait which means that the ThreadWorker remains waiting indefinitely (unless a spurious wake-up occurs) and so the call to join() in shutdown() can't be completed stopping the shutdown of the thread pool. One suggestion to fix this would be to provide a predicate to the wait(lock), such as
m_pool->m_conditional_lock.wait( lock , [this]{ return (!this->m_pool->m_queue.empty()) || this->m_pool->m_shutdown;});
The text was updated successfully, but these errors were encountered: