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;
   }