We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 5089

Summary: SDL_CondWaitTimeout causes deadlock when used in multi-threads.
Product: SDL Reporter: elite_jwp <elite_jwp>
Component: threadAssignee: Sam Lantinga <slouken>
Status: NEW --- QA Contact: Sam Lantinga <slouken>
Severity: major    
Priority: P2    
Version: 2.0.12   
Hardware: x86_64   
OS: Windows 10   
Attachments: this bug's comment
Modified the text format of first attachment file.

Description elite_jwp 2020-04-14 02:34:51 UTC
Created attachment 4305 [details]
this bug's comment

(This description also can be found in attachment file, which should be more easy to read due to the text format.)

I use the SDL_cond as below:

In some threads:
SDL_LockMutex(mtx);
SDL_CondWaitTimout(cond, mtx, 10);
SDL_UnlockMutex(mtx);

In another thread:
SDL_CondBroadcast(cond);

This will cause deadlock sometime.

I analyse the calling stream and find a issue:

Thread 1:                      					Thread 2:                      				Thread 3:
(SDL_CondWaitTimeout)          					(SDL_CondSignal	            				(SDL_CondWaitTimeout)
												/SDL_CondBroadcast)

....
SDL_LockMutex(cond->lock);
++cond->waiting;
SDL_UnlockMutex(cond->lock);
SDL_UnlokcMutex(mutex);

// Here timeout when waiting
retval=SDL_SemWaitTimeout(cond->wait_sem, ms);
												...
												SDL_LockMutex(cond->lock);
												if(cond->waiting > cond->signals) {
													++cond->signals;
													SDL_SemPost(cond->wait_sem);
													SDL_UnlockMutex(cond->lock);
													SDL_SemWait(cond->wait_done);
												}
												...
																						....
																						SDL_LockMutex(cond->lock);
																						++cond->waiting;
																						SDL_UnlockMutex(cond->lock);
																						SDL_UnlokcMutex(mutex);

																						// Here catch the semaphore signaled in thread 2
																						retval=SDL_SemWaitTimeout(cond->wait_sem, ms);										
SDL_LockMutex(cond->lock);
if (cond->signals > 0) {
	if (retval > 0) {
		// !!!Here deadlock occurs as the
		// semaphore catched by thread 3.
		SDL_SemWait(cond->wait_sem);
    }
    SDL_SemPost(cond->wait_done);

    --cond->signals;
}
--cond->waiting;
SDL_UnlockMutex(cond->lock);
SDL_LockMutex(mutex);																	SDL_LockMutex(cond->lock);
																						if (cond->signals > 0) {
																							if (retval > 0) {
																								// !!!Here deadlock occurs as the
																								// semaphore catched by thread 3.
																								SDL_SemWait(cond->wait_sem);
																							}
																							SDL_SemPost(cond->wait_done);

																							--cond->signals;
																						}
																						--cond->waiting;
																						SDL_UnlockMutex(cond->lock);
																						SDL_LockMutex(mutex);
Comment 1 elite_jwp 2020-04-14 03:01:25 UTC
Created attachment 4306 [details]
Modified the text format of first attachment file.