1
0
mirror of https://github.com/apache/httpd.git synced 2026-01-06 09:01:14 +03:00

Fix shm, rmm, and lock problems.

PR: 16057


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@808150 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Daniel Earl Poirier
2009-08-26 18:29:49 +00:00
parent 60fbe11de1
commit 1bc6da5bb4
2 changed files with 87 additions and 35 deletions

View File

@@ -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>]

View File

@@ -80,11 +80,9 @@
#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);
if (sts != APR_SUCCESS) {
log_error_and_cleanup("failed to create shared memory segments", sts, s);
return;
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;
}
client_list = apr_rmm_malloc(client_rmm, sizeof(*client_list) +
sizeof(client_entry*)*num_buckets);
/* 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 initialize rmm", sts, s);
return !OK;
}
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,