apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Klaus Keppler <klaus.kepp...@informatik.stud.uni-erlangen.de>
Subject [PATCH] apr_thread_cond_wait bug/problem on WIN32
Date Fri, 05 Mar 2004 14:46:36 GMT
[RESENT because I got no response for about two weeks...]


Hello,

having spent several hours on one problem only occuring on WIN32
platform I found following bug(?) with locks/win32/thread_cond.c.

In my application I use the function apr_thread_cond_wait in a
very similar context like httpd2's worker-mpm (fdqueue.c ->
ap_queue_pop).
Heavy load tests (using apache's ab) worked well under linux,
but on win32 I experienced deadlocks after some seconds.

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 for *me* 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
loops before ending in an deadlock; now I tested 200.000 loops without
problems.

Btw: another approach would be to add a counter to every mutex and
ignore unlock calls when counter==0. Would this make sense?

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) {


--
Klaus Keppler <klaus.keppler@informatik.stud.uni-erlangen.de>
Student of Computer Science at University Erlangen-Nurember, Germany



Mime
View raw message