You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2001/10/02 18:11:13 UTC
cvs commit: apache-1.3/src/modules/standard mod_unique_id.c
wrowe 01/10/02 09:11:13
Modified: src/modules/standard mod_unique_id.c
Log:
Steal a play from mod_proxy, which taught us this Win32 lesson. Threaded
local storage must be allocated with the Tls*() family of functions, or
the dynamically loaded module _will_ clobber our clib's (msvcrt's) own
thread saftey stacks.
I _don't_ know what the other multithread platforms require in terms of
initialization. OS2/Netware maintainers can steal the idea from the
Win32 get_cur_unique_id() implementation, to initialize other copies
on the fly (if required.) They may already call child_init for every
thread, so child_init could call the master_init to set up this thread's
variables. Remember that the get_cur_unique_id() applies to straight
un*x fork implementations as well, so protect with #ifdef PLAT sections.
Revision Changes Path
1.26 +89 -37 apache-1.3/src/modules/standard/mod_unique_id.c
Index: mod_unique_id.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_unique_id.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- mod_unique_id.c 2001/09/26 14:59:29 1.25
+++ mod_unique_id.c 2001/10/02 16:11:13 1.26
@@ -144,8 +144,63 @@
static unsigned global_in_addr;
-static APACHE_TLS unique_id_rec cur_unique_id;
+#ifdef WIN32
+static DWORD tls_index;
+
+BOOL WINAPI DllMain (HINSTANCE dllhandle, DWORD reason, LPVOID reserved)
+{
+ LPVOID memptr;
+
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ tls_index = TlsAlloc();
+ case DLL_THREAD_ATTACH: /* intentional no break */
+ TlsSetValue(tls_index, calloc(sizeof(unique_id_rec), 1));
+ break;
+ case DLL_THREAD_DETACH:
+ memptr = TlsGetValue(tls_index);
+ if (memptr) {
+ free (memptr);
+ TlsSetValue (tls_index, 0);
+ }
+ break;
+ }
+
+ return TRUE;
+}
+
+static unique_id_rec* get_cur_unique_id(int parent)
+{
+ /* Apache initializes the child process, not the individual child threads.
+ * Copy the original parent record if this->pid is not yet initialized.
+ */
+ static unique_id_rec *parent_id;
+ unique_id_rec *cur_unique_id = (unique_id_rec *) TlsGetValue(tls_index);
+
+ if (parent) {
+ parent_id = cur_unique_id;
+ }
+ else if (!cur_unique_id->pid) {
+ memcpy(cur_unique_id, parent_id, sizeof(*parent_id));
+ }
+ return cur_unique_id;
+}
+
+#else /* !WIN32 */
+
+/* Even when not MULTITHREAD, this will return a single structure, since
+ * APACHE_TLS should be defined as empty on single-threaded platforms.
+ */
+static unique_id_rec* get_cur_unique_id(int parent)
+{
+ static APACHE_TLS unique_id_rec spcid;
+ return &spcid;
+}
+
+#endif /* !WIN32 */
+
+
/*
* Number of elements in the structure unique_id_rec.
*/
@@ -170,27 +225,28 @@
#ifndef NO_GETTIMEOFDAY
struct timeval tv;
#endif
+ unique_id_rec *cur_unique_id = get_cur_unique_id(1);
/*
* Calculate the sizes and offsets in cur_unique_id.
*/
unique_id_rec_offset[0] = XtOffsetOf(unique_id_rec, stamp);
- unique_id_rec_size[0] = sizeof(cur_unique_id.stamp);
+ unique_id_rec_size[0] = sizeof(cur_unique_id->stamp);
unique_id_rec_offset[1] = XtOffsetOf(unique_id_rec, in_addr);
- unique_id_rec_size[1] = sizeof(cur_unique_id.in_addr);
+ unique_id_rec_size[1] = sizeof(cur_unique_id->in_addr);
unique_id_rec_offset[2] = XtOffsetOf(unique_id_rec, pid);
- unique_id_rec_size[2] = sizeof(cur_unique_id.pid);
+ unique_id_rec_size[2] = sizeof(cur_unique_id->pid);
#ifdef MULTITHREAD
unique_id_rec_offset[3] = XtOffsetOf(unique_id_rec, tid);
- unique_id_rec_size[3] = sizeof(cur_unique_id.tid);
+ unique_id_rec_size[3] = sizeof(cur_unique_id->tid);
unique_id_rec_offset[4] = XtOffsetOf(unique_id_rec, counter);
- unique_id_rec_size[4] = sizeof(cur_unique_id.counter);
+ unique_id_rec_size[4] = sizeof(cur_unique_id->counter);
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[4];
#else
unique_id_rec_offset[3] = XtOffsetOf(unique_id_rec, counter);
- unique_id_rec_size[3] = sizeof(cur_unique_id.counter);
+ unique_id_rec_size[3] = sizeof(cur_unique_id->counter);
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];
#endif
@@ -255,12 +311,10 @@
static void unique_id_child_init(server_rec *s, pool *p)
{
pid_t pid;
-#ifdef MULTITHREAD
- tid_t tid;
-#endif
#ifndef NO_GETTIMEOFDAY
struct timeval tv;
#endif
+ unique_id_rec *cur_unique_id = get_cur_unique_id(1);
/*
* Note that we use the pid because it's possible that on the same
@@ -269,7 +323,7 @@
* children.
*/
pid = getpid();
- cur_unique_id.pid = pid;
+ cur_unique_id->pid = pid;
/*
* Test our assumption that the pid is 32-bits. It's possible that
@@ -277,23 +331,12 @@
* of them. It would have been really nice to test this during
* global_init ... but oh well.
*/
- if ((pid_t)cur_unique_id.pid != pid) {
+ if ((pid_t)cur_unique_id->pid != pid) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s,
"oh no! pids are greater than 32-bits! I'm broken!");
}
-
-#ifdef MULTITHREAD
- /*
- * Note that we use the pid because it's possible that on the same
- * physical machine there are multiple servers (i.e. using Listen). But
- * it's guaranteed that none of them will share the same pid+tids between
- * children.
- */
- tid = gettid();
- cur_unique_id.tid = tid;
-#endif
- cur_unique_id.in_addr = global_in_addr;
+ cur_unique_id->in_addr = global_in_addr;
/*
* If we use 0 as the initial counter we have a little less protection
@@ -302,16 +345,16 @@
*/
#ifndef NO_GETTIMEOFDAY
if (gettimeofday(&tv, NULL) == -1) {
- cur_unique_id.counter = 0;
+ cur_unique_id->counter = 0;
}
else {
/* Some systems have very low variance on the low end of their
* system counter, defend against that.
*/
- cur_unique_id.counter = tv.tv_usec / 10;
+ cur_unique_id->counter = tv.tv_usec / 10;
}
#else
- cur_unique_id.counter = 0;
+ cur_unique_id->counter = 0;
#endif
/*
@@ -319,11 +362,8 @@
* identifiers are comparable between machines of different byte
* orderings. Note in_addr is already in network order.
*/
- cur_unique_id.pid = htonl(cur_unique_id.pid);
-#ifdef MULTITHREAD
- cur_unique_id.tid = htonl(cur_unique_id.tid);
-#endif
- cur_unique_id.counter = htons(cur_unique_id.counter);
+ cur_unique_id->pid = htonl(cur_unique_id->pid);
+ cur_unique_id->counter = htons(cur_unique_id->counter);
}
/* NOTE: This is *NOT* the same encoding used by base64encode ... the last two
@@ -354,6 +394,7 @@
unsigned short counter;
const char *e;
int i,j,k;
+ unique_id_rec *cur_unique_id = get_cur_unique_id(0);
/* copy the unique_id if this is an internal redirect (we're never
* actually called for sub requests, so we don't need to test for
@@ -363,17 +404,28 @@
ap_table_setn(r->subprocess_env, "UNIQUE_ID", e);
return DECLINED;
}
+
+ cur_unique_id->stamp = htonl((unsigned int)r->request_time);
- cur_unique_id.stamp = htonl((unsigned int)r->request_time);
+#ifdef MULTITHREAD
+ /*
+ * Note that we use the pid because it's possible that on the same
+ * physical machine there are multiple servers (i.e. using Listen). But
+ * it's guaranteed that none of them will share the same pid+tids between
+ * children.
+ */
+ cur_unique_id->tid = gettid();
+ cur_unique_id->tid = htonl(cur_unique_id->tid);
+#endif
/* 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 *) cur_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 *) cur_unique_id) + unique_id_rec_offset[i];
for (j = 0; j < unique_id_rec_size[i]; j++, k++) {
x[k] = y[j];
}
@@ -407,8 +459,8 @@
ap_table_setn(r->subprocess_env, "UNIQUE_ID", str);
/* and increment the identifier for the next call */
- counter = ntohs(cur_unique_id.counter) + 1;
- cur_unique_id.counter = htons(counter);
+ counter = ntohs(cur_unique_id->counter) + 1;
+ cur_unique_id->counter = htons(counter);
return DECLINED;
}