mirror of
https://github.com/apache/httpd.git
synced 2026-01-26 19:01:35 +03:00
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
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user