]> granicus.if.org Git - apache/commitdiff
Session cache interface redesign, Part 6:
authorJoe Orton <jorton@apache.org>
Tue, 26 Feb 2008 16:57:56 +0000 (16:57 +0000)
committerJoe Orton <jorton@apache.org>
Tue, 26 Feb 2008 16:57:56 +0000 (16:57 +0000)
Move mutex handling up out of the session cache providers:

* modules/ssl/ssl_private.h (modssl_sesscache_provider): Add name and
  flags fields.  Define MODSSL_SESSCACHE_FLAG_NOTMPSAFE constant.

* modules/ssl/ssl_scache.c (ssl_scache_store, ssl_scache_retrieve,
  ssl_scache_remove, ssl_ext_status_hook): Lock and release the mutex
  around provider calls, if necessary.

* modules/ssl/ssl_engine_mutex.c (ssl_mutex_init): Do nothing if no
  session cache is configured, or the session cache does not require a
  mutex.  Otherwise, fail if no mutex is configured and the session
  cache *does* require a mutex.
  (ssl_mutex_on, ssl_mutex_off): Remove checks for mutex mode;
  functions now invoked only if necessary.

* modules/ssl/ssl_scache_dc.c, modules/ssl/ssl_scache_memcache: Set
  name and flags fields in provider structures.

* modules/ssl/ssl_scache_shmcb.c, modules/ssl_scache_dbm.c: Remove
  mutex handling through; set name and flags fields in provider
  structures; mark both as unsafe for concurrent access in flags.

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

modules/ssl/ssl_engine_mutex.c
modules/ssl/ssl_private.h
modules/ssl/ssl_scache.c
modules/ssl/ssl_scache_dbm.c
modules/ssl/ssl_scache_dc.c
modules/ssl/ssl_scache_memcache.c
modules/ssl/ssl_scache_shmcb.c

index bbcd92ad641d9c5ee1a51d0518569cc2741db35a..7c6145cbcdc1e8b2ab2eeac37431304a1e23cf99 100644 (file)
@@ -39,12 +39,24 @@ int ssl_mutex_init(server_rec *s, apr_pool_t *p)
     SSLModConfigRec *mc = myModConfig(s);
     apr_status_t rv;
 
-    if (mc->nMutexMode == SSL_MUTEXMODE_NONE)
+    /* A mutex is only needed if a session cache is configured, and
+     * the provider used is not internally multi-process/thread
+     * safe. */
+    if (!mc->sesscache
+        || (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) == 0) {
         return TRUE;
+    }
 
     if (mc->pMutex) {
         return TRUE;
     }
+    else if (mc->nMutexMode == SSL_MUTEXMODE_NONE) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                     "An SSLMutex is required for the '%s' session cache",
+                     mc->sesscache->name);
+        return FALSE;
+    }
+
     if ((rv = apr_global_mutex_create(&mc->pMutex, mc->szMutexFile,
                                       mc->nMutexMech, s->process->pool))
             != APR_SUCCESS) {
@@ -97,8 +109,6 @@ int ssl_mutex_on(server_rec *s)
     SSLModConfigRec *mc = myModConfig(s);
     apr_status_t rv;
 
-    if (mc->nMutexMode == SSL_MUTEXMODE_NONE)
-        return TRUE;
     if ((rv = apr_global_mutex_lock(mc->pMutex)) != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s,
                      "Failed to acquire SSL session cache lock");
@@ -112,8 +122,6 @@ int ssl_mutex_off(server_rec *s)
     SSLModConfigRec *mc = myModConfig(s);
     apr_status_t rv;
 
-    if (mc->nMutexMode == SSL_MUTEXMODE_NONE)
-        return TRUE;
     if ((rv = apr_global_mutex_unlock(mc->pMutex)) != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s,
                      "Failed to release SSL session cache lock");
index 0f20b535a28c5bc7831a9760ae0c554c227dd2b3..76f08c61d33213ab67d028a428745375cab59429 100644 (file)
@@ -354,8 +354,20 @@ typedef struct {
 #define MODSSL_SESSCACHE_PROVIDER_GROUP "mod_ssl-sesscache"
 #define MODSSL_SESSCACHE_PROVIDER_VERSION "0"
 
+/* If this flag is set, the store/retrieve/delete/status interfaces of
+ * the provider are NOT safe to be called concurrently from multiple
+ * processes or threads, and an external global mutex must be used to
+ * serialize access to the provider. */
+#define MODSSL_SESSCACHE_FLAG_NOTMPSAFE (0x0001)
+
 /* Session cache provider vtable. */
 typedef struct {
+    /* Canonical provider name: */
+    const char *name;
+
+    /* Bitmask of MODSSL_SESSCACHE_FLAG_* flags: */
+    unsigned int flags;
+
     /* Create a session cache based on the given configuration string
      * ARG.  Returns NULL on success, or an error string on failure.
      * Pool TMP should be used for any temporary allocations, pool P
index 3d97ee8d16711aefc828d2f4c19b2f74a3c70c10..db4dad12e84de510c19ccb99f142579a3ec3da79 100644 (file)
@@ -90,6 +90,7 @@ BOOL ssl_scache_store(server_rec *s, UCHAR *id, int idlen,
     SSLModConfigRec *mc = myModConfig(s);
     unsigned char encoded[SSL_SESSION_MAX_DER], *ptr;
     unsigned int len;
+    BOOL rv;
 
     /* Serialise the session. */
     len = i2d_SSL_SESSION(sess, NULL);
@@ -102,8 +103,18 @@ BOOL ssl_scache_store(server_rec *s, UCHAR *id, int idlen,
     ptr = encoded;
     len = i2d_SSL_SESSION(sess, &ptr);
 
-    return mc->sesscache->store(mc->sesscache_context, s, id, idlen, 
-                                expiry, encoded, len);
+    if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) {
+        ssl_mutex_on(s);
+    }
+    
+    rv = mc->sesscache->store(mc->sesscache_context, s, id, idlen, 
+                              expiry, encoded, len);
+
+    if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) {
+        ssl_mutex_off(s);
+    }
+
+    return rv;
 }
 
 SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen,
@@ -113,9 +124,20 @@ SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen,
     unsigned char dest[SSL_SESSION_MAX_DER];
     unsigned int destlen = SSL_SESSION_MAX_DER;
     MODSSL_D2I_SSL_SESSION_CONST unsigned char *ptr;
-    
-    if (mc->sesscache->retrieve(mc->sesscache_context, s, id, idlen, 
-                                dest, &destlen, p) == FALSE) {
+    BOOL rv;
+
+    if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) {
+        ssl_mutex_on(s);
+    }
+
+    rv = mc->sesscache->retrieve(mc->sesscache_context, s, id, idlen, 
+                                 dest, &destlen, p);
+
+    if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) {
+        ssl_mutex_off(s);
+    }
+
+    if (rv == FALSE) {
         return NULL;
     }
 
@@ -129,9 +151,15 @@ void ssl_scache_remove(server_rec *s, UCHAR *id, int idlen,
 {
     SSLModConfigRec *mc = myModConfig(s);
 
+    if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) {
+        ssl_mutex_on(s);
+    }
+
     mc->sesscache->delete(mc->sesscache_context, s, id, idlen, p);
 
-    return;
+    if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) {
+        ssl_mutex_off(s);
+    }
 }
 
 /*  _________________________________________________________________
@@ -153,8 +181,16 @@ static int ssl_ext_status_hook(request_rec *r, int flags)
     ap_rputs("</td></tr>\n", r);
     ap_rputs("<tr><td bgcolor=\"#ffffff\">\n", r);
 
+    if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) {
+        ssl_mutex_on(r->server);
+    }
+
     mc->sesscache->status(mc->sesscache_context, r, flags, r->pool);
 
+    if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) {
+        ssl_mutex_off(r->server);
+    }
+
     ap_rputs("</td></tr>\n", r);
     ap_rputs("</table>\n", r);
     return OK;
index acd2487222320741d3de872fa89b2ff127036185..5959d5ee81617269f35f33d3305d4839c9301f81 100644 (file)
@@ -71,7 +71,6 @@ static apr_status_t ssl_scache_dbm_init(void *context, server_rec *s, apr_pool_t
     }
 
     /* open it once to create it and to make sure it _can_ be created */
-    ssl_mutex_on(s);
     apr_pool_clear(ctx->pool);
 
     if ((rv = apr_dbm_open(&dbm, ctx->data_file,
@@ -79,7 +78,6 @@ static apr_status_t ssl_scache_dbm_init(void *context, server_rec *s, apr_pool_t
         ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
                      "Cannot create SSLSessionCache DBM file `%s'",
                      ctx->data_file);
-        ssl_mutex_off(s);
         return rv;
     }
     apr_dbm_close(dbm);
@@ -108,7 +106,6 @@ static apr_status_t ssl_scache_dbm_init(void *context, server_rec *s, apr_pool_t
         }
     }
 #endif
-    ssl_mutex_off(s);
     ssl_scache_dbm_expire(ctx, s);
 
     return APR_SUCCESS;
@@ -173,7 +170,6 @@ static BOOL ssl_scache_dbm_store(void *context, server_rec *s, UCHAR *id, int id
     memcpy((char *)dbmval.dptr+sizeof(time_t), ucaData, nData);
 
     /* and store it to the DBM file */
-    ssl_mutex_on(s);
     apr_pool_clear(ctx->pool);
 
     if ((rv = apr_dbm_open(&dbm, ctx->data_file,
@@ -182,7 +178,6 @@ static BOOL ssl_scache_dbm_store(void *context, server_rec *s, UCHAR *id, int id
                      "Cannot open SSLSessionCache DBM file `%s' for writing "
                      "(store)",
                      ctx->data_file);
-        ssl_mutex_off(s);
         free(dbmval.dptr);
         return FALSE;
     }
@@ -191,12 +186,10 @@ static BOOL ssl_scache_dbm_store(void *context, server_rec *s, UCHAR *id, int id
                      "Cannot store SSL session to DBM file `%s'",
                      ctx->data_file);
         apr_dbm_close(dbm);
-        ssl_mutex_off(s);
         free(dbmval.dptr);
         return FALSE;
     }
     apr_dbm_close(dbm);
-    ssl_mutex_off(s);
 
     /* free temporary buffers */
     free(dbmval.dptr);
@@ -231,7 +224,6 @@ static BOOL ssl_scache_dbm_retrieve(void *context, server_rec *s, const UCHAR *i
      * XXX: Should we open the dbm against r->pool so the cleanup will
      * do the apr_dbm_close? This would make the code a bit cleaner.
      */
-    ssl_mutex_on(s);
     apr_pool_clear(ctx->pool);
     if ((rc = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, 
                            SSL_DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) {
@@ -239,18 +231,15 @@ static BOOL ssl_scache_dbm_retrieve(void *context, server_rec *s, const UCHAR *i
                      "Cannot open SSLSessionCache DBM file `%s' for reading "
                      "(fetch)",
                      ctx->data_file);
-        ssl_mutex_off(s);
         return FALSE;
     }
     rc = apr_dbm_fetch(dbm, dbmkey, &dbmval);
     if (rc != APR_SUCCESS) {
         apr_dbm_close(dbm);
-        ssl_mutex_off(s);
         return FALSE;
     }
     if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(time_t)) {
         apr_dbm_close(dbm);
-        ssl_mutex_off(s);
         return FALSE;
     }
 
@@ -258,7 +247,6 @@ static BOOL ssl_scache_dbm_retrieve(void *context, server_rec *s, const UCHAR *i
     nData = dbmval.dsize-sizeof(time_t);
     if (nData > *destlen) {
         apr_dbm_close(dbm);
-        ssl_mutex_off(s);
         return FALSE;
     }    
 
@@ -267,7 +255,6 @@ static BOOL ssl_scache_dbm_retrieve(void *context, server_rec *s, const UCHAR *i
     memcpy(dest, (char *)dbmval.dptr + sizeof(time_t), nData);
 
     apr_dbm_close(dbm);
-    ssl_mutex_off(s);
 
     /* make sure the stuff is still not expired */
     now = time(NULL);
@@ -292,7 +279,6 @@ static void ssl_scache_dbm_remove(void *context, server_rec *s, UCHAR *id, int i
     dbmkey.dsize = idlen;
 
     /* and delete it from the DBM file */
-    ssl_mutex_on(s);
     apr_pool_clear(ctx->pool);
 
     if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, 
@@ -301,12 +287,10 @@ static void ssl_scache_dbm_remove(void *context, server_rec *s, UCHAR *id, int i
                      "Cannot open SSLSessionCache DBM file `%s' for writing "
                      "(delete)",
                      ctx->data_file);
-        ssl_mutex_off(s);
         return;
     }
     apr_dbm_delete(dbm, dbmkey);
     apr_dbm_close(dbm);
-    ssl_mutex_off(s);
 
     return;
 }
@@ -333,10 +317,7 @@ static void ssl_scache_dbm_expire(struct context *ctx, server_rec *s)
      */
     tNow = time(NULL);
 
-    ssl_mutex_on(s);
-
     if (tNow < ctx->last_expiry + sc->session_cache_timeout) {
-        ssl_mutex_off(s);
         return;
     }
 
@@ -415,7 +396,6 @@ static void ssl_scache_dbm_expire(struct context *ctx, server_rec *s)
         if (keyidx < KEYMAX)
             break;
     }
-    ssl_mutex_off(s);
 
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "Inter-Process Session Cache (DBM) Expiry: "
@@ -437,7 +417,6 @@ static void ssl_scache_dbm_status(void *context, request_rec *r,
 
     nElem = 0;
     nSize = 0;
-    ssl_mutex_on(r->server);
 
     apr_pool_clear(ctx->pool);
     if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, 
@@ -446,7 +425,6 @@ static void ssl_scache_dbm_status(void *context, request_rec *r,
                      "Cannot open SSLSessionCache DBM file `%s' for status "
                      "retrival",
                      ctx->data_file);
-        ssl_mutex_off(r->server);
         return;
     }
     /*
@@ -461,7 +439,6 @@ static void ssl_scache_dbm_status(void *context, request_rec *r,
         nSize += dbmval.dsize;
     }
     apr_dbm_close(dbm);
-    ssl_mutex_off(r->server);
     if (nSize > 0 && nElem > 0)
         nAverage = nSize / nElem;
     else
@@ -473,6 +450,8 @@ static void ssl_scache_dbm_status(void *context, request_rec *r,
 }
 
 const modssl_sesscache_provider modssl_sesscache_dbm = {
+    "dbm",
+    MODSSL_SESSCACHE_FLAG_NOTMPSAFE,
     ssl_scache_dbm_create,
     ssl_scache_dbm_init,
     ssl_scache_dbm_kill,
index fa0ff5393c380fae66d720f3af6836d705ff58fc..9067db91651d59e7d50ecdb3ff36b4ed54435b43 100644 (file)
@@ -171,6 +171,8 @@ static void ssl_scache_dc_status(void *context, request_rec *r, int flags, apr_p
 }
 
 const modssl_sesscache_provider modssl_sesscache_dc = {
+    "distcache",
+    0,
     ssl_scache_dc_create,
     ssl_scache_dc_init,
     ssl_scache_dc_kill,
index 52917e29caa4bbe61fc7346f05384780ccfef9fb..4622c223f39558713d35725ca6759549a4dbeb44 100644 (file)
@@ -292,6 +292,8 @@ static void ssl_scache_mc_status(void *context, request_rec *r,
 }
 
 const modssl_sesscache_provider modssl_sesscache_mc = {
+    "memcache",
+    0,
     ssl_scache_mc_create,
     ssl_scache_mc_init,
     ssl_scache_mc_kill,
index 6c9b114e8ceefc8c3ccbf24840d27de375303742..0eddf2354929d986c90ae5c5684b79a1e8471725 100644 (file)
@@ -429,33 +429,28 @@ static BOOL ssl_scache_shmcb_store(void *context, server_rec *s,
                                    unsigned char *encoded,
                                    unsigned int len_encoded)
 {
-    BOOL to_return = FALSE;
     struct context *ctx = context;
     SHMCBHeader *header = ctx->header;
     SHMCBSubcache *subcache = SHMCB_MASK(header, id);
 
-    ssl_mutex_on(s);
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "ssl_scache_shmcb_store (0x%02x -> subcache %d)",
                  SHMCB_MASK_DBG(header, id));
     if (idlen < 4) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short session_id provided "
                 "(%u bytes)", idlen);
-        goto done;
+        return FALSE;
     }
     if (!shmcb_subcache_store(s, header, subcache, encoded,
                               len_encoded, id, idlen, timeout)) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                      "can't store a session!");
-        goto done;
+        return FALSE;
     }
     header->stat_stores++;
-    to_return = TRUE;
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "leaving ssl_scache_shmcb_store successfully");
-done:
-    ssl_mutex_off(s);
-    return to_return;
+    return TRUE;
 }
 
 static BOOL ssl_scache_shmcb_retrieve(void *context, server_rec *s, 
@@ -468,7 +463,6 @@ static BOOL ssl_scache_shmcb_retrieve(void *context, server_rec *s,
     SHMCBSubcache *subcache = SHMCB_MASK(header, id);
     BOOL rv;
 
-    ssl_mutex_on(s);
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "ssl_scache_shmcb_retrieve (0x%02x -> subcache %d)",
                  SHMCB_MASK_DBG(header, id));
@@ -484,7 +478,6 @@ static BOOL ssl_scache_shmcb_retrieve(void *context, server_rec *s,
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "leaving ssl_scache_shmcb_retrieve successfully");
 
-    ssl_mutex_off(s);
     return rv;
 }
 
@@ -495,14 +488,13 @@ static void ssl_scache_shmcb_remove(void *context, server_rec *s,
     SHMCBHeader *header = ctx->header;
     SHMCBSubcache *subcache = SHMCB_MASK(header, id);
 
-    ssl_mutex_on(s);
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "ssl_scache_shmcb_remove (0x%02x -> subcache %d)",
                  SHMCB_MASK_DBG(header, id));
     if (idlen < 4) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short session_id provided "
                 "(%u bytes)", idlen);
-        goto done;
+        return;
     }
     if (shmcb_subcache_remove(s, header, subcache, id, idlen))
         header->stat_removes_hit++;
@@ -510,8 +502,6 @@ static void ssl_scache_shmcb_remove(void *context, server_rec *s,
         header->stat_removes_miss++;
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "leaving ssl_scache_shmcb_remove successfully");
-done:
-    ssl_mutex_off(s);
 }
 
 static void ssl_scache_shmcb_status(void *context, request_rec *r, 
@@ -530,7 +520,6 @@ static void ssl_scache_shmcb_status(void *context, request_rec *r,
     /* Perform the iteration inside the mutex to avoid corruption or invalid
      * pointer arithmetic. The rest of our logic uses read-only header data so
      * doesn't need the lock. */
-    ssl_mutex_on(s);
     /* Iterate over the subcaches */
     for (loop = 0; loop < header->subcache_num; loop++) {
         SHMCBSubcache *subcache = SHMCB_SUBCACHE(header, loop);
@@ -549,7 +538,6 @@ static void ssl_scache_shmcb_status(void *context, request_rec *r,
                 min_expiry = ((idx_expiry < min_expiry) ? idx_expiry : min_expiry);
         }
     }
-    ssl_mutex_off(s);
     index_pct = (100 * total) / (header->index_num *
                                  header->subcache_num);
     cache_pct = (100 * cache_total) / (header->subcache_data_size *
@@ -832,6 +820,8 @@ static BOOL shmcb_subcache_remove(server_rec *s, SHMCBHeader *header,
 }
 
 const modssl_sesscache_provider modssl_sesscache_shmcb = {
+    "shmcb",
+    MODSSL_SESSCACHE_FLAG_NOTMPSAFE,
     ssl_scache_shmcb_create,
     ssl_scache_shmcb_init,
     ssl_scache_shmcb_kill,