From: Roy T. Fielding Date: Thu, 26 Aug 1999 17:22:35 +0000 (+0000) Subject: Modifications to make mod_unique_id thread safe. This should work on Windows, X-Git-Tag: PRE_APR_CHANGES~13 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3dfd8e0dc33c806df7e96fe2e4600a3b19fc23fe;p=apache Modifications to make mod_unique_id thread safe. This should work on Windows, but no guarantees. I haven't verified it will always give a unique ID, but the logic is good. I'll write some test cases to see if I can make it fail later. Submitted by: Ryan Bloom git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@83789 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/metadata/mod_unique_id.c b/modules/metadata/mod_unique_id.c index 63474ed1fe..09a1756cd3 100644 --- a/modules/metadata/mod_unique_id.c +++ b/modules/metadata/mod_unique_id.c @@ -65,19 +65,25 @@ #include "httpd.h" #include "http_config.h" #include "http_log.h" -#include "multithread.h" - -#ifdef MULTITHREAD -#error sorry this module does not support multithreaded servers yet -#endif typedef struct { unsigned int stamp; unsigned int in_addr; unsigned int pid; unsigned short counter; + unsigned int thread_index; } unique_id_rec; +/* We are using thread_index (the index into the scoreboard), because we + * cannont garauntee the thread_id will be an integer. + * + * This code looks like it won't give a unique ID with the new thread logic. + * It will. The reason is, we don't increment the counter in a thread_safe + * manner. Because the thread_index is also in the unique ID now, this does + * not matter. In order for the id to not be unique, the same thread would + * have to get the same counter twice in the same second. + */ + /* Comments: * * We want an identifier which is unique across all hits, everywhere. @@ -143,12 +149,12 @@ typedef struct { static unsigned global_in_addr; -static APACHE_TLS unique_id_rec cur_unique_id; +static unique_id_rec cur_unique_id; /* * Number of elements in the structure unique_id_rec. */ -#define UNIQUE_ID_REC_MAX 4 +#define UNIQUE_ID_REC_MAX 5 static unsigned short unique_id_rec_offset[UNIQUE_ID_REC_MAX], unique_id_rec_size[UNIQUE_ID_REC_MAX], @@ -177,8 +183,11 @@ static void unique_id_global_init(server_rec *s, pool *p) unique_id_rec_size[2] = sizeof(cur_unique_id.pid); unique_id_rec_offset[3] = XtOffsetOf(unique_id_rec, counter); unique_id_rec_size[3] = sizeof(cur_unique_id.counter); + unique_id_rec_offset[4] = XtOffsetOf(unique_id_rec, thread_index); + unique_id_rec_size[4] = sizeof(cur_unique_id.thread_index); unique_id_rec_total_size = unique_id_rec_size[0] + unique_id_rec_size[1] + - unique_id_rec_size[2] + unique_id_rec_size[3]; + unique_id_rec_size[2] + unique_id_rec_size[3] + + unique_id_rec_size[4]; /* * Calculate the size of the structure when encoded. @@ -316,6 +325,7 @@ static int gen_unique_id(request_rec *r) * Buffer padded with two final bytes, used to copy the unique_id_red * structure without the internal paddings that it could have. */ + unique_id_rec new_unique_id; struct { unique_id_rec foo; unsigned char pad[2]; @@ -332,16 +342,21 @@ static int gen_unique_id(request_rec *r) ap_table_setn(r->subprocess_env, "UNIQUE_ID", e); return DECLINED; } + + new_unique_id.in_addr = cur_unique_id.in_addr; + new_unique_id.pid = cur_unique_id.pid; + new_unique_id.counter = cur_unique_id.counter; - cur_unique_id.stamp = htonl((unsigned int)r->request_time); + new_unique_id.stamp = htonl((unsigned int)r->request_time); + new_unique_id.thread_index = htonl((unsigned int)r->connection->thread_num); /* we'll use a temporal buffer to avoid uuencoding the possible internal * paddings of the original structure */ x = (unsigned char *) &paddedbuf; - y = (unsigned char *) &cur_unique_id; + y = (unsigned char *) &new_unique_id; k = 0; for (i = 0; i < UNIQUE_ID_REC_MAX; i++) { - y = ((unsigned char *) &cur_unique_id) + unique_id_rec_offset[i]; + y = ((unsigned char *) &new_unique_id) + unique_id_rec_offset[i]; for (j = 0; j < unique_id_rec_size[i]; j++, k++) { x[k] = y[j]; } @@ -370,7 +385,8 @@ static int gen_unique_id(request_rec *r) ap_table_setn(r->subprocess_env, "UNIQUE_ID", str); /* and increment the identifier for the next call */ - counter = ntohs(cur_unique_id.counter) + 1; + + counter = ntohs(new_unique_id.counter) + 1; cur_unique_id.counter = htons(counter); return DECLINED;