Opened 13 years ago

Closed 10 years ago

#3628 closed Bugs (invalid)

condition.notify_one() does not wake up a thread that is in condition.wait() or condition.timed_wait()

Reported by: Shouaib Ahmed <ranashoaib@…> Owned by: viboes
Milestone: To Be Determined Component: thread
Version: Boost 1.40.0 Severity: Problem
Keywords: condition Cc:

Description

You can see in the attached project's TestBoostThread.cpp file that in ThreadFuncWaiter(), the thread is in timed_wait() call before it releases the mutex to let the ThreadFuncNotifier() thread notify it. But inside notify_one(), most of the time it will choose not to notify any "waiter". The total_count class member is 0 when that happens. If I uncomment the three lines marked as WORKAROUND_ in TestBoostThread.cpp, then the threads will be notified, but this is just a workaround.

Attachments (1)

TestBoostThread.zip (3.8 KB ) - added by Shouaib Ahmed <ranashoaib@…> 13 years ago.

Download all attachments as: .zip

Change History (11)

by Shouaib Ahmed <ranashoaib@…>, 13 years ago

Attachment: TestBoostThread.zip added

in reply to:  description comment:1 by Shouaib Ahmed <ranashoaib@…>, 13 years ago

Just wanted to mention that I am using Visual Studio 2008 on Windows XP.

Replying to Shouaib Ahmed <ranashoaib@…>:

You can see in the attached project's TestBoostThread.cpp file that in ThreadFuncWaiter(), the thread is in timed_wait() call before it releases the mutex to let the ThreadFuncNotifier() thread notify it. But inside notify_one(), most of the time it will choose not to notify any "waiter". The total_count class member is 0 when that happens. If I uncomment the three lines marked as WORKAROUND_ in TestBoostThread.cpp, then the threads will be notified, but this is just a workaround.

in reply to:  description ; comment:2 by viboes, 13 years ago

Replying to Shouaib Ahmed <ranashoaib@…>:

You can see in the attached project's TestBoostThread.cpp file that in ThreadFuncWaiter(), the thread is in timed_wait() call before it releases the mutex to let the ThreadFuncNotifier() thread notify it. But inside notify_one(), most of the time it will choose not to notify any "waiter". The total_count class member is 0 when that happens. If I uncomment the three lines marked as WORKAROUND_ in TestBoostThread.cpp, then the threads will be notified, but this is just a workaround.

Have you tried to protect with a mutex the theConditions variable? This variable is used by ThreadFuncNotifier() and ThreadFuncWaiter().

in reply to:  2 ; comment:3 by Shouaib Ahmed <ranashoaib@…>, 13 years ago

Replying to viboes:

Replying to Shouaib Ahmed <ranashoaib@…>:

You can see in the attached project's TestBoostThread.cpp file that in ThreadFuncWaiter(), the thread is in timed_wait() call before it releases the mutex to let the ThreadFuncNotifier() thread notify it. But inside notify_one(), most of the time it will choose not to notify any "waiter". The total_count class member is 0 when that happens. If I uncomment the three lines marked as WORKAROUND_ in TestBoostThread.cpp, then the threads will be notified, but this is just a workaround.

Have you tried to protect with a mutex the theConditions variable? This variable is used by ThreadFuncNotifier() and ThreadFuncWaiter().

It is protected by a mutex. May be you overlooked that.

in reply to:  3 comment:4 by viboes, 13 years ago

Replying to Shouaib Ahmed <ranashoaib@…>:

Replying to viboes:

Replying to Shouaib Ahmed <ranashoaib@…>:

You can see in the attached project's TestBoostThread.cpp file that in ThreadFuncWaiter(), the thread is in timed_wait() call before it releases the mutex to let the ThreadFuncNotifier() thread notify it. But inside notify_one(), most of the time it will choose not to notify any "waiter". The total_count class member is 0 when that happens. If I uncomment the three lines marked as WORKAROUND_ in TestBoostThread.cpp, then the threads will be notified, but this is just a workaround.

Have you tried to protect with a mutex the theConditions variable? This variable is used by ThreadFuncNotifier() and ThreadFuncWaiter().

It is protected by a mutex. May be you overlooked that.

You are right, I overlooked this mutex.

To which total_count class member are you referring to?

The explanation I found is that if you don't add the workaround, the thread ThreadFuncNotifier will lock the mutex during the iteration through the theConditions container + 500 (miliseconds?). This left enough time to make the wait for 50 milliseconds to expire. IMO you should not protect the Sleep neither in the thread ThreadFuncNotifier nor ThreadFuncWaiter.

The WORKAROUND_ Sleep(50); seems no necessary to me. Does it works without? HTH.

comment:5 by anonymous, 12 years ago

See also ticket:2330

comment:6 by viboes, 11 years ago

Milestone: Boost 1.41.0To Be Determined
Owner: changed from Anthony Williams to viboes
Status: newassigned

comment:7 by viboes, 10 years ago

Why do you need a recursive mutex?

comment:8 by viboes, 10 years ago

With

		unsigned int i = 0;
		for (Conditions::iterator it = theConditions.begin(); 
			it != theConditions.end() && i < 2; 
			++it)
		{			
			(*it)->notify_one();
			//WORKAROUND_ lockMtx.unlock();
			//WORKAROUND_ Sleep(50);
			cout << "Notified One " << theConditions.size() << endl;
			++i; 
			//WORKAROUND_ lockMtx.lock();
		}

only the two first conditions will be notified, so there will be up to 10 threads that will not be notified.

comment:9 by viboes, 10 years ago

I think that I understand why it could occur that sometimes some threads are not notified.

Both threads have a lock on theMutex. The underlying OS could choose to schedule the ThreadFuncNotifier thread as many times as it wants. One of the threads ThreadFuncWaiter ends by timeout as the ThreadFuncNotifier is not signaling the specific condition.

Let me know if you don't agree with my analysis. I will close the ticket as there is no evidence there is an issue on the library.

comment:10 by viboes, 10 years ago

Resolution: invalid
Status: assignedclosed
Note: See TracTickets for help on using tickets.