From 64122d18ddffb83f70192a1036c4fc601485a0cd Mon Sep 17 00:00:00 2001 From: pk910 Date: Sat, 14 Jan 2012 19:04:38 +0100 Subject: [PATCH] fixed WHOHandler.c multithread compatibility --- src/ClientSocket.c | 4 +- src/WHOHandler.c | 91 +++++++++++++++++++++------------------------- src/WHOHandler.h | 3 +- 3 files changed, 46 insertions(+), 52 deletions(-) diff --git a/src/ClientSocket.c b/src/ClientSocket.c index 83a2e28..80f4c37 100644 --- a/src/ClientSocket.c +++ b/src/ClientSocket.c @@ -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) { diff --git a/src/WHOHandler.c b/src/WHOHandler.c index 63232f7..5ad4ce6 100644 --- a/src/WHOHandler.c +++ b/src/WHOHandler.c @@ -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); diff --git a/src/WHOHandler.h b/src/WHOHandler.h index cf53406..d402878 100644 --- a/src/WHOHandler.h +++ b/src/WHOHandler.h @@ -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); -- 2.20.1