DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT <http://issues.apache.org/bugzilla/show_bug.cgi?id=27654>. ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND INSERTED IN THE BUG DATABASE.
http://issues.apache.org/bugzilla/show_bug.cgi?id=27654 Deadlock in apr_thread_cond_wait on WIN32 platform [PatchAvailable] Summary: Deadlock in apr_thread_cond_wait on WIN32 platform [PatchAvailable] Product: APR Version: 0.9.4 Platform: PC OS/Version: Windows NT/2K Status: NEW Severity: Normal Priority: Other Component: APR AssignedTo: [email protected] ReportedBy: [EMAIL PROTECTED] There seems to be a bug in the condition variable implementation on WIN32 platforms (see locks/win32/thread_cond.c). An application using apr_thread_cond_wait will run very well under linux (see httpd2's worker-mpm: fdqueue.c -> ap_queue_pop uses condition variables). But under WIN32 already with two threads using the same condition variable a deadlock occurs after short time. Debugging brought me to the source of apr_thread_cond_wait(); as you can see the function "apr_thread_mutex_unlock(mutex)" is called every time the while(1)-loop is run. I think this shouldn't be a problem in general (since an unlocked mutex can't be unlocked once more), but at least on WIN32 it *did* cause trouble. And I am no windows guru so I don't know if/how windows bothers about multiple unlocking. After changing the code to unlock the mutex only once everything worked very fine. :-) I tested the patch with Win2K. Without patch, my application ran (with 2 worker threads) only up to 20-30 loops before ending in an deadlock; now I tested 200.000 loops without problems. Another approach would be to add a counter to every mutex and ignore unlock calls when counter==0. Klaus --- locks/win32/thread_cond-old.c Mon Feb 23 11:56:45 2004 +++ locks/win32/thread_cond.c Mon Feb 23 12:01:46 2004 @@ -85,6 +85,8 @@ { DWORD res; + int unlock_once = 1; + while (1) { res = WaitForSingleObject(cond->mutex, INFINITE); if (res != WAIT_OBJECT_0) { @@ -93,7 +95,10 @@ cond->num_waiting++; ReleaseMutex(cond->mutex); - apr_thread_mutex_unlock(mutex); + if (unlock_once) { + unlock_once = 0; + apr_thread_mutex_unlock(mutex); + } res = WaitForSingleObject(cond->event, INFINITE); cond->num_waiting--; if (res != WAIT_OBJECT_0) { @@ -125,6 +130,8 @@ DWORD res; DWORD timeout_ms = (DWORD) apr_time_as_msec(timeout); + int unlock_once = 1; + while (1) { res = WaitForSingleObject(cond->mutex, timeout_ms); if (res != WAIT_OBJECT_0) { @@ -136,7 +143,10 @@ cond->num_waiting++; ReleaseMutex(cond->mutex); - apr_thread_mutex_unlock(mutex); + if (unlock_once) { + unlock_once = 0; + apr_thread_mutex_unlock(mutex); + } res = WaitForSingleObject(cond->event, timeout_ms); cond->num_waiting--; if (res != WAIT_OBJECT_0) { --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
