Opened 14 years ago
Closed 14 years ago
#1950 closed Bugs (invalid)
pthread/condition_variable::wait() unlocks associated mutex prematurely and may miss a notification
Reported by: | Owned by: | Anthony Williams | |
---|---|---|---|
Milestone: | Boost 1.36.0 | Component: | thread |
Version: | Boost 1.35.0 | Severity: | Showstopper |
Keywords: | pthread_cond_wait condition variable pthread mutex | Cc: |
Description
pthread implementation of class condition_variable implements wait() is as follows:
template<typename lock_type> void wait(lock_type& m) {
int res=0; {
detail::interruption_checker check_for_interruption(&cond); {
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); m.unlock(); res=pthread_cond_wait(&cond,&internal_mutex);
} m.lock();
} if(res) {
throw condition_error();
}
}
Each condition variable must have an associated mutex. pthread_cond_wait() must enter with the mutex locked. Having the mutex locked guarantees that no notifications will be missed by the receiving thread.
The above implementation releases mutex before entering pthread_cond_wait(). This creates an opportunity for pre-emption of the thread just after the mutex was unlocked, but before pthread has been entered. If another thread pre-empts at this point and tries to notify this condition variable, this notification will be missed by this thread.
Substitution of some random, unrelated mutex into pthread_cond_wait() is not a solution. It is the original mutex that is associated with the condition that must be passed to pthread_cond_wait().
Note that the same internal mutex is locked in both notify_one and notify_all. It is not possible to call pthread_cond_signal or pthread_cond_broadcast through the boost::condition_variable_any interface whilst a waiting thread is in the gap you highlighted.