]> granicus.if.org Git - apache/commitdiff
Fix shm, rmm, and lock problems.
authorDaniel Earl Poirier <poirier@apache.org>
Wed, 26 Aug 2009 18:29:49 +0000 (18:29 +0000)
committerDaniel Earl Poirier <poirier@apache.org>
Wed, 26 Aug 2009 18:29:49 +0000 (18:29 +0000)
PR: 16057

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@808150 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/aaa/mod_auth_digest.c

diff --git a/CHANGES b/CHANGES
index 39a932fb35340760fa4252beab171e57c5e46408..174e9a2a3ffb772b45f2e7de957d9486d280fc8a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,9 @@
 
 Changes with Apache 2.3.3
 
+  *) mod_auth_digest: Fix usage of shared memory and re-enable it.
+     PR 16057 [Dan Poirier]
+
   *) Preserve Port information over internal redirects
      PR 35999 [Jonas Ringh <jonas.ringh cixit.se>]
 
index 6dfbea615f2e3442b3159026a217e9462be88940..b3a1251a7ad3153ee8c4a80ba9a5eb3dd9319bbd 100644 (file)
 
 #include "mod_auth.h"
 
-/* Disable shmem until pools/init gets sorted out
- * remove following two lines when fixed
- */
-#undef APR_HAS_SHARED_MEMORY
-#define APR_HAS_SHARED_MEMORY 0
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 
 /* struct to hold the configuration info */
 
@@ -181,8 +179,9 @@ static unsigned long  *opaque_cntr;
 static apr_time_t     *otn_counter;     /* one-time-nonce counter */
 static apr_global_mutex_t *client_lock = NULL;
 static apr_global_mutex_t *opaque_lock = NULL;
-static char           client_lock_name[L_tmpnam];
-static char           opaque_lock_name[L_tmpnam];
+static const char     *client_lock_name;
+static const char     *opaque_lock_name;
+static const char     *client_shm_filename;
 
 #define DEF_SHMEM_SIZE  1000L           /* ~ 12 entries */
 #define DEF_NUM_BUCKETS 15L
@@ -204,6 +203,11 @@ static apr_status_t cleanup_tables(void *not_used)
                   "Digest: cleaning up shared memory");
     fflush(stderr);
 
+    if (client_rmm) {
+        apr_rmm_destroy(client_rmm);
+        client_rmm = NULL;
+    }
+
     if (client_shm) {
         apr_shm_destroy(client_shm);
         client_shm = NULL;
@@ -259,24 +263,56 @@ static void log_error_and_cleanup(char *msg, apr_status_t sts, server_rec *s)
 
 #if APR_HAS_SHARED_MEMORY
 
-static void initialize_tables(server_rec *s, apr_pool_t *ctx)
+static int initialize_tables(server_rec *s, apr_pool_t *ctx)
 {
     unsigned long idx;
     apr_status_t   sts;
+    const char *tempdir; 
 
     /* set up client list */
 
-    sts = apr_shm_create(&client_shm, shmem_size, tmpnam(NULL), ctx);
+    sts = apr_temp_dir_get(&tempdir, ctx);
+    if (APR_SUCCESS != sts) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, sts, s, 
+                     "Failed to find temporary directory");
+        log_error_and_cleanup("failed to find temp dir", sts, s);
+        return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    /* Create the shared memory segment */
+
+    /* 
+     * Create a unique filename using our pid. This information is 
+     * stashed in the global variable so the children inherit it.
+     */
+    client_shm_filename = apr_psprintf(ctx, "%s/authdigest_shm.%"APR_PID_T_FMT, tempdir, 
+                                       getpid());
+
+    /* Now create that segment */
+    sts = apr_shm_create(&client_shm, shmem_size,
+                        client_shm_filename, ctx);
+    if (APR_SUCCESS != sts) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, sts, s, 
+                     "Failed to create shared memory segment on file %s", 
+                     client_shm_filename);
+        log_error_and_cleanup("failed to initialize shm", sts, s);
+        return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    sts = apr_rmm_init(&client_rmm,
+                       NULL, /* no lock, we'll do the locking ourselves */
+                       apr_shm_baseaddr_get(client_shm),
+                       shmem_size, ctx);
     if (sts != APR_SUCCESS) {
-        log_error_and_cleanup("failed to create shared memory segments", sts, s);
-        return;
+        log_error_and_cleanup("failed to initialize rmm", sts, s);
+        return !OK;
     }
 
-    client_list = apr_rmm_malloc(client_rmm, sizeof(*client_list) +
-                                            sizeof(client_entry*)*num_buckets);
+    client_list = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(*client_list) +
+                                                          sizeof(client_entry*)*num_buckets));
     if (!client_list) {
         log_error_and_cleanup("failed to allocate shared memory", -1, s);
-        return;
+        return !OK;
     }
     client_list->table = (client_entry**) (client_list + 1);
     for (idx = 0; idx < num_buckets; idx++) {
@@ -285,50 +321,51 @@ static void initialize_tables(server_rec *s, apr_pool_t *ctx)
     client_list->tbl_len     = num_buckets;
     client_list->num_entries = 0;
 
-    tmpnam(client_lock_name);
+    client_lock_name = apr_psprintf(ctx, "%s/authdigest_lock.%"APR_PID_T_FMT, tempdir, 
+                                    getpid());
     /* FIXME: get the client_lock_name from a directive so we're portable
      * to non-process-inheriting operating systems, like Win32. */
     sts = apr_global_mutex_create(&client_lock, client_lock_name,
                                   APR_LOCK_DEFAULT, ctx);
     if (sts != APR_SUCCESS) {
         log_error_and_cleanup("failed to create lock (client_lock)", sts, s);
-        return;
+        return !OK;
     }
 
 
     /* setup opaque */
 
-    opaque_cntr = apr_rmm_malloc(client_rmm, sizeof(*opaque_cntr));
+    opaque_cntr = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(*opaque_cntr)));
     if (opaque_cntr == NULL) {
         log_error_and_cleanup("failed to allocate shared memory", -1, s);
-        return;
+        return !OK;
     }
     *opaque_cntr = 1UL;
 
-    tmpnam(opaque_lock_name);
-    /* FIXME: get the opaque_lock_name from a directive so we're portable
-     * to non-process-inheriting operating systems, like Win32. */
+    opaque_lock_name = apr_psprintf(ctx, "%s/authdigest_opaque_lock.%"APR_PID_T_FMT,
+                                    tempdir, 
+                                    getpid());
     sts = apr_global_mutex_create(&opaque_lock, opaque_lock_name,
                                   APR_LOCK_DEFAULT, ctx);
     if (sts != APR_SUCCESS) {
         log_error_and_cleanup("failed to create lock (opaque_lock)", sts, s);
-        return;
+        return !OK;
     }
 
 
     /* setup one-time-nonce counter */
 
-    otn_counter = apr_rmm_malloc(client_rmm, sizeof(*otn_counter));
+    otn_counter = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(*otn_counter)));
     if (otn_counter == NULL) {
         log_error_and_cleanup("failed to allocate shared memory", -1, s);
-        return;
+        return !OK;
     }
     *otn_counter = 0;
     /* no lock here */
 
 
     /* success */
-    return;
+    return OK;
 }
 
 #endif /* APR_HAS_SHARED_MEMORY */
@@ -364,7 +401,10 @@ static int initialize_module(apr_pool_t *p, apr_pool_t *plog,
      * last child dies. Therefore we can never clean up the old stuff,
      * creating a creeping memory leak.
      */
-    initialize_tables(s, p);
+    if (initialize_tables(s, p) != OK) {
+        return !OK;
+    }
+    /* Call cleanup_tables on exit or restart */
     apr_pool_cleanup_register(p, NULL, cleanup_tables, apr_pool_cleanup_null);
 #endif  /* APR_HAS_SHARED_MEMORY */
     return OK;
@@ -378,15 +418,21 @@ static void initialize_child(apr_pool_t *p, server_rec *s)
         return;
     }
 
-    /* FIXME: get the client_lock_name from a directive so we're portable
-     * to non-process-inheriting operating systems, like Win32. */
+    /* Get access to rmm in child */
+    sts = apr_rmm_attach(&client_rmm,
+                         NULL,
+                         apr_shm_baseaddr_get(client_shm),
+                         p);
+    if (sts != APR_SUCCESS) {
+        log_error_and_cleanup("failed to attach to rmm", sts, s);
+        return;
+    }
+
     sts = apr_global_mutex_child_init(&client_lock, client_lock_name, p);
     if (sts != APR_SUCCESS) {
         log_error_and_cleanup("failed to create lock (client_lock)", sts, s);
         return;
     }
-    /* FIXME: get the opaque_lock_name from a directive so we're portable
-     * to non-process-inheriting operating systems, like Win32. */
     sts = apr_global_mutex_child_init(&opaque_lock, opaque_lock_name, p);
     if (sts != APR_SUCCESS) {
         log_error_and_cleanup("failed to create lock (opaque_lock)", sts, s);
@@ -775,7 +821,7 @@ static long gc(void)
             client_list->table[idx] = NULL;
         }
         if (entry) {                    /* remove entry */
-            apr_rmm_free(client_rmm, (apr_rmm_off_t)entry);
+            apr_rmm_free(client_rmm, apr_rmm_offset_get(client_rmm, entry));
             num_removed++;
         }
     }
@@ -811,7 +857,7 @@ static client_entry *add_client(unsigned long key, client_entry *info,
 
     /* try to allocate a new entry */
 
-    entry = (client_entry *)apr_rmm_malloc(client_rmm, sizeof(client_entry));
+    entry = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(client_entry)));
     if (!entry) {
         long num_removed = gc();
         ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
@@ -820,8 +866,11 @@ static client_entry *add_client(unsigned long key, client_entry *info,
                      "%ld", num_removed,
                      client_list->num_created - client_list->num_renewed,
                      client_list->num_removed, client_list->num_renewed);
-        entry = (client_entry *)apr_rmm_malloc(client_rmm, sizeof(client_entry));
+        entry = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(client_entry)));
         if (!entry) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                         "unable to allocate new auth_digest client");
+            apr_global_mutex_unlock(client_lock);
             return NULL;       /* give up */
         }
     }
@@ -1093,7 +1142,7 @@ static client_entry *gen_client(const request_rec *r)
 
     apr_global_mutex_lock(opaque_lock);
     op = (*opaque_cntr)++;
-    apr_global_mutex_lock(opaque_lock);
+    apr_global_mutex_unlock(opaque_lock);
 
     if (!(entry = add_client(op, &new_entry, r->server))) {
         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,