fixed WHOHandler.c multithread compatibility
authorpk910 <philipp@zoelle1.de>
Sat, 14 Jan 2012 18:04:38 +0000 (19:04 +0100)
committerpk910 <philipp@zoelle1.de>
Sat, 14 Jan 2012 18:06:27 +0000 (19:06 +0100)
src/ClientSocket.c
src/WHOHandler.c
src/WHOHandler.h

index 83a2e281c8bf8bf91a4cdc6edbbd0dfde6223954..80f4c37d2cae7f73fa4cdd4b996858bfa528d551 100644 (file)
@@ -445,9 +445,11 @@ void socket_loop(int timeout_seconds) {
                     sock->bufferpos -= used;
                 }
                 is_synchronized = 0;
+                unsigned long tid = syscall(SYS_gettid);
+                whohandler_start_of_recv(sock, tid);
                 DESYNCHRONIZE(synchronized_recv);
                 parse_lines(sock, linesbuf, used);
-                whohandler_end_of_recv(sock); //WHOHandler hack (unlock WHOQueue mutexes)
+                whohandler_end_of_recv(sock, tid); //WHOHandler hack (unlock WHOQueue mutexes)
                 #else
                 int used = parse_lines(sock, sock->buffer, sock->bufferpos);
                 if(used == sock->bufferpos + 1) {
index 63232f7c7998d0be5451118cecb9cedfb662172b..5ad4ce6f302bf53bb7f5db8e5742700312650242 100644 (file)
@@ -39,13 +39,16 @@ struct WHOQueueEntry {
     struct WHOQueueEntry *next;
     void *callback[MAXCALLBACKS];
     void *data[MAXCALLBACKS];
-    #ifdef HAVE_THREADS
-    unsigned long lock_tid;
-    pthread_mutex_t lock_mutex;
-    int lock_count;
-    #endif
 };
 
+#ifdef HAVE_THREADS
+struct ParseOrder {
+    unsigned long tid;
+    struct ParseOrder *next;
+};
+struct ParseOrder *parse_order = NULL;
+#endif
+
 static int checkWHOID(struct ClientSocket *client, int whoid) {
     struct WHOQueueEntry *entry;
     for(entry = client->whoqueue_first; entry; entry = entry->next) {
@@ -74,11 +77,6 @@ static struct WHOQueueEntry* addWHOQueueEntry(struct ClientSocket *client) {
     }
     entry->next = NULL;
     entry->whoid = whoid;
-    #ifdef HAVE_THREADS
-    entry->lock_tid = 0;
-    THREAD_MUTEX_INIT(entry->lock_mutex);
-    entry->lock_count = 0;
-    #endif
     if(client->whoqueue_last) {
         client->whoqueue_last->next = entry;
     } else {
@@ -106,15 +104,6 @@ static struct WHOQueueEntry* getNextWHOQueueEntry(struct ClientSocket *client, i
         if(entry == client->whoqueue_last) {
             client->whoqueue_last = NULL;
         }
-        #ifdef HAVE_THREADS
-        entry->lock_tid = -1;
-        if(entry->lock_count) {
-            int i;
-            for(i = 0; i < entry->lock_count; i++) {
-                DESYNCHRONIZE(entry->lock_mutex); //unlock ALL
-            }
-        }
-        #endif
     }
     DESYNCHRONIZE(whohandler_sync);
     return entry;
@@ -126,15 +115,6 @@ void clear_whoqueue(struct ClientSocket *client) {
     struct WHOQueueEntry *entry, *next;
     for(entry = client->whoqueue_first; entry; entry = next) {
         next = entry->next;
-        #ifdef HAVE_THREADS
-        entry->lock_tid = -1;
-        if(entry->lock_count) {
-            int i;
-            for(i = 0; i < entry->lock_count; i++) {
-                DESYNCHRONIZE(entry->lock_mutex); //unlock ALL
-            }
-        }
-        #endif
         free(entry);
     }
     client->whoqueue_last = NULL;
@@ -143,15 +123,36 @@ void clear_whoqueue(struct ClientSocket *client) {
 }
 
 #if HAVE_THREADS
-void whohandler_end_of_recv(struct ClientSocket *client) {
+void whohandler_start_of_recv(struct ClientSocket *client, unsigned long tid) {
     SYNCHRONIZE(whohandler_sync);
-    unsigned long tid = syscall(SYS_gettid);
-    struct WHOQueueEntry *entry;
-    for(entry = client->whoqueue_first; entry; entry = entry->next) {
-        if(entry->lock_tid == tid) {
-            entry->lock_tid = 0;
-            DESYNCHRONIZE(entry->lock_mutex);
-        }
+    struct ParseOrder *entry, *last;
+    for(last = parse_order; last; last = last->next) {
+        if(last->next == NULL)
+            break;
+    }
+    entry = malloc(sizeof(*entry));
+    entry->tid = tid;
+    entry->next = NULL;
+    if(last)
+        last->next = entry;
+    else
+        parse_order = entry;
+    DESYNCHRONIZE(whohandler_sync);
+}
+
+void whohandler_end_of_recv(struct ClientSocket *client, unsigned long tid) {
+    SYNCHRONIZE(whohandler_sync);
+    struct ParseOrder *entry, *last = NULL;
+    for(entry = parse_order; entry; entry = entry->next) {
+        if(entry->tid == tid) {
+            if(last)
+                last->next = entry->next;
+            else
+                parse_order = entry->next;
+            free(entry);
+            break;
+        } else
+            last = entry;
     }
     DESYNCHRONIZE(whohandler_sync);
 }
@@ -286,13 +287,8 @@ static void _recv_whohandler_354(struct ClientSocket *client, char **argv, unsig
     if(entry == NULL) return;
     #ifdef HAVE_THREADS
     unsigned long tid = syscall(SYS_gettid);
-    if(entry->lock_tid != tid) {
-        entry->lock_count++;
-        SYNCHRONIZE(entry->lock_mutex);
-        if(entry->lock_tid == -1) {
-            return; //entry has been destroyed
-        }
-        entry->lock_tid = tid;
+    while(parse_order->tid != tid) {
+        usleep(5000); //5ms
     }
     #endif
     if(entry->type & WHOQUEUETYPE_USERLIST) {
@@ -385,13 +381,8 @@ static void _recv_whohandler_315(struct ClientSocket *client, char **argv, unsig
     if(entry == NULL) return;
     #ifdef HAVE_THREADS
     unsigned long tid = syscall(SYS_gettid);
-    if(entry->lock_tid != tid) {
-        entry->lock_count++;
-        SYNCHRONIZE(entry->lock_mutex);
-        if(entry->lock_tid == -1) {
-            return; //entry has been destroyed
-        }
-        entry->lock_tid = tid;
+    while(parse_order->tid != tid) {
+        usleep(5000); //5ms
     }
     #endif
     getNextWHOQueueEntry(client, type, 1);
index cf5340624a608c37e25a0955070e284a821dc185..d4028787991cc0a83a4789a010ce2845ee3116de 100644 (file)
@@ -31,7 +31,8 @@ typedef USERAUTH_CALLBACK(userauth_callback_t);
 
 void clear_whoqueue(struct ClientSocket *client);
 #if HAVE_THREADS
-void whohandler_end_of_recv(struct ClientSocket *client);
+void whohandler_start_of_recv(struct ClientSocket *client, unsigned long tid);
+void whohandler_end_of_recv(struct ClientSocket *client, unsigned long tid);
 #endif
 void recv_whohandler_354(struct ClientSocket *client, char **argv, unsigned int argc);
 void recv_whohandler_315(struct ClientSocket *client, char **argv, unsigned int argc);