ASF Bugzilla – Attachment 35723 Details for
Bug 62044
shared memory segments are not found in global list, but appear to exist in kernel.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Reuse SHMs names on restart or stop/start (2.4.x)
httpd-2.4.x-PR62044.patch (text/plain), 38.09 KB, created by
Yann Ylavic
on 2018-02-08 16:32:13 UTC
(
hide
)
Description:
Reuse SHMs names on restart or stop/start (2.4.x)
Filename:
MIME Type:
Creator:
Yann Ylavic
Created:
2018-02-08 16:32:13 UTC
Size:
38.09 KB
patch
obsolete
>Index: modules/proxy/mod_proxy_balancer.c >=================================================================== >--- modules/proxy/mod_proxy_balancer.c (revision 1823575) >+++ modules/proxy/mod_proxy_balancer.c (working copy) >@@ -22,6 +22,7 @@ > #include "apr_version.h" > #include "ap_hooks.h" > #include "apr_date.h" >+#include "apr_escape.h" > #include "mod_watchdog.h" > > static const char *balancer_mutex_type = "proxy-balancer-shm"; >@@ -730,6 +731,115 @@ static apr_status_t lock_remove(void *data) > return(0); > } > >+/* >+ * Compute an ID for a vhost based on what makes it selected by requests. >+ * The second and more Host(s)/IP(s):port(s), and the ServerAlias(es) are >+ * optional (see make_servers_ids() below). >+ */ >+ static const char *make_server_id(server_rec *s, apr_pool_t *p, int full) >+{ >+ apr_md5_ctx_t md5_ctx; >+ unsigned char md5[APR_MD5_DIGESTSIZE]; >+ char host_ip[64]; /* for any IPv[46] string */ >+ server_addr_rec *sar; >+ int i; >+ >+ apr_md5_init(&md5_ctx); >+ for (sar = s->addrs; sar; sar = sar->next) { >+ host_ip[0] = '\0'; >+ apr_sockaddr_ip_getbuf(host_ip, sizeof host_ip, sar->host_addr); >+ apr_md5_update(&md5_ctx, (void *)sar->virthost, strlen(sar->virthost)); >+ apr_md5_update(&md5_ctx, (void *)host_ip, strlen(host_ip)); >+ apr_md5_update(&md5_ctx, (void *)&sar->host_port, >+ sizeof(sar->host_port)); >+ if (!full) { >+ break; >+ } >+ } >+ if (s->server_hostname) { >+ apr_md5_update(&md5_ctx, (void *)s->server_hostname, >+ strlen(s->server_hostname)); >+ } >+ if (full) { >+ if (s->names) { >+ for (i = 0; i < s->names->nelts; ++i) { >+ const char *name = APR_ARRAY_IDX(s->names, i, char *); >+ apr_md5_update(&md5_ctx, (void *)name, strlen(name)); >+ } >+ } >+ if (s->wild_names) { >+ for (i = 0; i < s->wild_names->nelts; ++i) { >+ const char *name = APR_ARRAY_IDX(s->wild_names, i, char *); >+ apr_md5_update(&md5_ctx, (void *)name, strlen(name)); >+ } >+ } >+ } >+ apr_md5_final(md5, &md5_ctx); >+ >+ return apr_pescape_hex(p, md5, sizeof md5, 0); >+} >+ >+/* >+ * First try to compute an unique ID for each vhost with minimal criteria, >+ * that is the first Host/IP:port and ServerName. For most cases this should >+ * be enough and avoids changing the ID unnecessarily accross restart (or >+ * stop/start w.r.t. persisted files) for things that this module does not >+ * care about. >+ * >+ * But if it's not enough (collisions) do a second pass for the full monty, >+ * that is additionally the other Host(s)/IP(s):port(s) and ServerAlias(es). >+ * >+ * Finally, for pathological configs where this is still not enough, let's >+ * append a counter to duplicates, because we really want that ID to be unique >+ * even if the vhost will never be selected to handle requests at run time, at >+ * load time a duplicate may steal the original slotmems (depending on its >+ * balancers' configurations), see how mod_slotmem_shm reuses slots/files based >+ * solely on this ID and resets them if the sizes don't match. >+ */ >+static apr_array_header_t *make_servers_ids(server_rec *main_s, apr_pool_t *p) >+{ >+ server_rec *s = main_s; >+ apr_array_header_t *ids = apr_array_make(p, 10, sizeof(const char *)); >+ apr_hash_t *dups = apr_hash_make(p); >+ int idx, *dup, full_monty = 0; >+ const char *id; >+ >+ for (idx = 0, s = main_s; s; s = s->next, ++idx) { >+ id = make_server_id(s, p, 0); >+ dup = apr_hash_get(dups, id, APR_HASH_KEY_STRING); >+ apr_hash_set(dups, id, APR_HASH_KEY_STRING, >+ apr_pmemdup(p, &idx, sizeof(int))); >+ if (dup) { >+ full_monty = 1; >+ APR_ARRAY_IDX(ids, *dup, const char *) = NULL; >+ APR_ARRAY_PUSH(ids, const char *) = NULL; >+ } >+ else { >+ APR_ARRAY_PUSH(ids, const char *) = id; >+ } >+ } >+ if (full_monty) { >+ apr_hash_clear(dups); >+ for (idx = 0, s = main_s; s; s = s->next, ++idx) { >+ id = APR_ARRAY_IDX(ids, idx, const char *); >+ if (id) { >+ /* Preserve non-duplicates */ >+ continue; >+ } >+ id = make_server_id(s, p, 1); >+ if (apr_hash_get(dups, id, APR_HASH_KEY_STRING)) { >+ id = apr_psprintf(p, "%s_%x", id, idx); >+ } >+ else { >+ apr_hash_set(dups, id, APR_HASH_KEY_STRING, (void *)-1); >+ } >+ APR_ARRAY_IDX(ids, idx, const char *) = id; >+ } >+ } >+ >+ return ids; >+} >+ > /* post_config hook: */ > static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog, > apr_pool_t *ptemp, server_rec *s) >@@ -738,6 +848,8 @@ static int balancer_post_config(apr_pool_t *pconf, > proxy_server_conf *conf; > ap_slotmem_instance_t *new = NULL; > apr_time_t tstamp; >+ apr_array_header_t *ids; >+ int idx; > > /* balancer_post_config() will be called twice during startup. So, don't > * set up the static data the 1st time through. */ >@@ -768,14 +880,16 @@ static int balancer_post_config(apr_pool_t *pconf, > return !OK; > } > >+ ids = make_servers_ids(s, ptemp); >+ > tstamp = apr_time_now(); > /* > * Go thru each Vhost and create the shared mem slotmem for > * each balancer's workers > */ >- while (s) { >+ for (idx = 0; s; ++idx) { > int i,j; >- char *id; >+ const char *id; > proxy_balancer *balancer; > ap_slotmem_type_t type; > void *sconf = s->module_config; >@@ -784,14 +898,7 @@ static int balancer_post_config(apr_pool_t *pconf, > * During create_proxy_config() we created a dummy id. Now that > * we have identifying info, we can create the real id > */ >- id = apr_psprintf(pconf, "%s.%s.%d.%s.%s.%u.%s", >- (s->server_scheme ? s->server_scheme : "????"), >- (s->server_hostname ? s->server_hostname : "???"), >- (int)s->port, >- (s->server_admin ? s->server_admin : "??"), >- (s->defn_name ? s->defn_name : "?"), >- s->defn_line_number, >- (s->error_fname ? s->error_fname : DEFAULT_ERRORLOG)); >+ id = APR_ARRAY_IDX(ids, idx, const char *); > conf->id = apr_psprintf(pconf, "p%x", > ap_proxy_hashfunc(id, PROXY_HASHFUNC_DEFAULT)); > if (conf->bslot) { >Index: modules/slotmem/mod_slotmem_shm.c >=================================================================== >--- modules/slotmem/mod_slotmem_shm.c (revision 1823575) >+++ modules/slotmem/mod_slotmem_shm.c (working copy) >@@ -25,11 +25,11 @@ > > #include "httpd.h" > #include "http_main.h" >-#include "ap_mpm.h" /* for ap_mpm_query() */ >+#include "http_core.h" > >-#define AP_SLOTMEM_IS_PREGRAB(t) (t->desc.type & AP_SLOTMEM_TYPE_PREGRAB) >-#define AP_SLOTMEM_IS_PERSIST(t) (t->desc.type & AP_SLOTMEM_TYPE_PERSIST) >-#define AP_SLOTMEM_IS_CLEARINUSE(t) (t->desc.type & AP_SLOTMEM_TYPE_CLEARINUSE) >+#define AP_SLOTMEM_IS_PREGRAB(t) (t->desc->type & AP_SLOTMEM_TYPE_PREGRAB) >+#define AP_SLOTMEM_IS_PERSIST(t) (t->desc->type & AP_SLOTMEM_TYPE_PERSIST) >+#define AP_SLOTMEM_IS_CLEARINUSE(t) (t->desc->type & AP_SLOTMEM_TYPE_CLEARINUSE) > > /* The description of the slots to reuse the slotmem */ > typedef struct { >@@ -47,24 +47,31 @@ struct ap_slotmem_instance_t { > int fbased; /* filebased? */ > void *shm; /* ptr to memory segment (apr_shm_t *) */ > void *base; /* data set start */ >- apr_pool_t *gpool; /* per segment global pool */ >+ apr_pool_t *pool; /* per segment pool (generation cleared) */ > char *inuse; /* in-use flag table*/ > unsigned int *num_free; /* slot free count for this instance */ > void *persist; /* persist dataset start */ >- sharedslotdesc_t desc; /* per slot desc */ >+ const sharedslotdesc_t *desc; /* per slot desc */ > struct ap_slotmem_instance_t *next; /* location of next allocated segment */ > }; > > /* >- * Memory layout: >- * sharedslotdesc_t | num_free | slots | isuse array | >- * ^ ^ >- * | . base >- * . persist (also num_free) >+ * Layout for SHM and persited file : >+ * >+ * +-------------------------------------------------------------+~> >+ * | desc | num_free | base (slots) | inuse (array) | md5 | desc | compat.. >+ * +------+-----------------------------------------+------------+~> >+ * ^ ^ ^ \ / ^ : >+ * |______|_____________ SHM (mem->@) ______________| | _____|__/ >+ * | |/ | >+ * | ^ v | >+ * |_____________________ File (mem->persist + [meta]) __| > */ > >+ > /* global pool and list of slotmem we are handling */ >-static struct ap_slotmem_instance_t *globallistmem = NULL; >+static struct ap_slotmem_instance_t *globallistmem = NULL, >+ **retained_globallistmem = NULL; > static apr_pool_t *gpool = NULL; > > #define DEFAULT_SLOTMEM_PREFIX "slotmem-shm-" >@@ -71,31 +78,6 @@ static apr_pool_t *gpool = NULL; > #define DEFAULT_SLOTMEM_SUFFIX ".shm" > #define DEFAULT_SLOTMEM_PERSIST_SUFFIX ".persist" > >-/* Unixes (and Netware) have the unlink() semantic, which allows to >- * apr_file_remove() a file still in use (opened elsewhere), the inode >- * remains until the last fd is closed, whereas any file created with >- * the same name/path will use a new inode. >- * >- * On windows and OS/2 ("\SHAREMEM\..." tree), apr_file_remove() marks >- * the files for deletion until the last HANDLE is closed, meanwhile the >- * same file/path can't be opened/recreated. >- * Thus on graceful restart (the only restart mode with mpm_winnt), the >- * old file may still exist until all the children stop, while we ought >- * to create a new one for our new clear SHM. Therefore, we would only >- * be able to reuse (attach) the old SHM, preventing some changes to >- * the config file, like the number of balancers/members, since the >- * size checks (to fit the new config) would fail. Let's avoid this by >- * including the generation number in the SHM filename (obviously not >- * the persisted name!) >- */ >-#ifndef SLOTMEM_UNLINK_SEMANTIC >-#if defined(WIN32) || defined(OS2) >-#define SLOTMEM_UNLINK_SEMANTIC 0 >-#else >-#define SLOTMEM_UNLINK_SEMANTIC 1 >-#endif >-#endif >- > /* > * Persist the slotmem in a file > * slotmem name and file name. >@@ -113,18 +95,9 @@ static int slotmem_filenames(apr_pool_t *pool, > > if (slotname && *slotname && strcasecmp(slotname, "none") != 0) { > if (slotname[0] != '/') { >-#if !SLOTMEM_UNLINK_SEMANTIC >- /* Each generation needs its own file name. */ >- int generation = 0; >- ap_mpm_query(AP_MPMQ_GENERATION, &generation); >- fname = apr_psprintf(pool, "%s%s_%x%s", DEFAULT_SLOTMEM_PREFIX, >- slotname, generation, DEFAULT_SLOTMEM_SUFFIX); >-#else >- /* Reuse the same file name for each generation. */ > fname = apr_pstrcat(pool, DEFAULT_SLOTMEM_PREFIX, > slotname, DEFAULT_SLOTMEM_SUFFIX, > NULL); >-#endif > fname = ap_runtime_dir_relative(pool, fname); > } > else { >@@ -135,17 +108,6 @@ static int slotmem_filenames(apr_pool_t *pool, > } > > if (persistname) { >- /* Persisted file names are immutable... */ >-#if !SLOTMEM_UNLINK_SEMANTIC >- if (slotname[0] != '/') { >- pname = apr_pstrcat(pool, DEFAULT_SLOTMEM_PREFIX, >- slotname, DEFAULT_SLOTMEM_SUFFIX, >- DEFAULT_SLOTMEM_PERSIST_SUFFIX, >- NULL); >- pname = ap_runtime_dir_relative(pool, pname); >- } >- else >-#endif > pname = apr_pstrcat(pool, fname, > DEFAULT_SLOTMEM_PERSIST_SUFFIX, > NULL); >@@ -170,7 +132,7 @@ static void slotmem_clearinuse(ap_slotmem_instance > > inuse = slot->inuse; > >- for (i = 0; i < slot->desc.num; i++, inuse++) { >+ for (i = 0; i < slot->desc->num; i++, inuse++) { > if (*inuse) { > *inuse = 0; > (*slot->num_free)++; >@@ -191,11 +153,11 @@ static void store_slotmem(ap_slotmem_instance_t *s > > if (storename) { > rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE, >- APR_OS_DEFAULT, slotmem->gpool); >+ APR_OS_DEFAULT, slotmem->pool); > if (APR_STATUS_IS_EEXIST(rv)) { >- apr_file_remove(storename, slotmem->gpool); >+ apr_file_remove(storename, slotmem->pool); > rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE, >- APR_OS_DEFAULT, slotmem->gpool); >+ APR_OS_DEFAULT, slotmem->pool); > } > if (rv != APR_SUCCESS) { > return; >@@ -203,28 +165,36 @@ static void store_slotmem(ap_slotmem_instance_t *s > if (AP_SLOTMEM_IS_CLEARINUSE(slotmem)) { > slotmem_clearinuse(slotmem); > } >- nbytes = (slotmem->desc.size * slotmem->desc.num) + >- (slotmem->desc.num * sizeof(char)) + AP_UNSIGNEDINT_OFFSET; >+ nbytes = (slotmem->desc->size * slotmem->desc->num) + >+ (slotmem->desc->num * sizeof(char)) + AP_UNSIGNEDINT_OFFSET; > apr_md5(digest, slotmem->persist, nbytes); > rv = apr_file_write_full(fp, slotmem->persist, nbytes, NULL); > if (rv == APR_SUCCESS) { > rv = apr_file_write_full(fp, digest, APR_MD5_DIGESTSIZE, NULL); > } >+ if (rv == APR_SUCCESS) { >+ rv = apr_file_write_full(fp, slotmem->desc, AP_SLOTMEM_OFFSET, >+ NULL); >+ } > apr_file_close(fp); > if (rv != APR_SUCCESS) { >- apr_file_remove(storename, slotmem->gpool); >+ apr_file_remove(storename, slotmem->pool); > } > } > } > >-static apr_status_t restore_slotmem(void *ptr, const char *storename, >- apr_size_t size, apr_pool_t *pool) >+static apr_status_t restore_slotmem(sharedslotdesc_t *desc, >+ const char *storename, apr_size_t size, >+ apr_pool_t *pool) > { > apr_file_t *fp; >- apr_size_t nbytes = size; >- apr_status_t rv = APR_SUCCESS; >+ apr_status_t rv = APR_ENOTIMPL; >+ void *ptr = (char *)desc + AP_SLOTMEM_OFFSET; >+ apr_size_t dsize = size - AP_SLOTMEM_OFFSET; >+ apr_size_t nbytes = dsize; > unsigned char digest[APR_MD5_DIGESTSIZE]; > unsigned char digest2[APR_MD5_DIGESTSIZE]; >+ char desc_buf[AP_SLOTMEM_OFFSET]; > > ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02335) > "restoring %s", storename); >@@ -234,7 +204,7 @@ static void store_slotmem(ap_slotmem_instance_t *s > pool); > if (rv == APR_SUCCESS) { > rv = apr_file_read(fp, ptr, &nbytes); >- if ((rv == APR_SUCCESS || rv == APR_EOF) && nbytes == size) { >+ if ((rv == APR_SUCCESS || rv == APR_EOF) && nbytes == dsize) { > rv = APR_SUCCESS; /* for successful return @ EOF */ > /* > * if at EOF, don't bother checking md5 >@@ -243,28 +213,61 @@ static void store_slotmem(ap_slotmem_instance_t *s > if (apr_file_eof(fp) != APR_EOF) { > apr_size_t ds = APR_MD5_DIGESTSIZE; > rv = apr_file_read(fp, digest, &ds); >- if ((rv == APR_SUCCESS || rv == APR_EOF) && >- ds == APR_MD5_DIGESTSIZE) { >- rv = APR_SUCCESS; >+ if ((rv == APR_SUCCESS || rv == APR_EOF) >+ && ds == APR_MD5_DIGESTSIZE) { > apr_md5(digest2, ptr, nbytes); > if (memcmp(digest, digest2, APR_MD5_DIGESTSIZE)) { >- ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, >- APLOGNO(02551) "bad md5 match"); >- rv = APR_EGENERAL; >+ rv = APR_EMISMATCH; > } >+ /* >+ * if at EOF, don't bother checking desc >+ * - backwards compatibility >+ * */ >+ else if (apr_file_eof(fp) != APR_EOF) { >+ nbytes = sizeof(desc_buf); >+ rv = apr_file_read(fp, desc_buf, &nbytes); >+ if ((rv == APR_SUCCESS || rv == APR_EOF) >+ && nbytes == sizeof(desc_buf)) { >+ if (memcmp(desc, desc_buf, nbytes)) { >+ rv = APR_EMISMATCH; >+ } >+ else { >+ rv = APR_SUCCESS; >+ } >+ } >+ else if (rv == APR_SUCCESS || rv == APR_EOF) { >+ rv = APR_INCOMPLETE; >+ } >+ } >+ else { >+ rv = APR_EOF; >+ } > } >+ else if (rv == APR_SUCCESS || rv == APR_EOF) { >+ rv = APR_INCOMPLETE; >+ } > } > else { >- ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, >- APLOGNO(02552) "at EOF... bypassing md5 match check (old persist file?)"); >+ rv = APR_EOF; > } >+ if (rv == APR_EMISMATCH) { >+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02551) >+ "persisted slotmem md5/desc mismatch"); >+ } >+ else if (rv == APR_EOF) { >+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(02552) >+ "persisted slotmem at EOF... bypassing md5/desc match check " >+ "(old persist file?)"); >+ rv = APR_SUCCESS; >+ } > } >- else if (nbytes != size) { >- ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, >- APLOGNO(02553) "Expected %" APR_SIZE_T_FMT ": Read %" APR_SIZE_T_FMT, >- size, nbytes); >- rv = APR_EGENERAL; >+ else if (rv == APR_SUCCESS || rv == APR_EOF) { >+ rv = APR_INCOMPLETE; > } >+ if (rv == APR_INCOMPLETE) { >+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02553) >+ "persisted slotmem read had unexpected size"); >+ } > apr_file_close(fp); > } > } >@@ -271,26 +274,45 @@ static void store_slotmem(ap_slotmem_instance_t *s > return rv; > } > >-static apr_status_t cleanup_slotmem(void *param) >+static apr_status_t cleanup_slotmem(void *is_startup) > { >- ap_slotmem_instance_t **mem = param; >+ int is_exiting = (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_EXITING); >+ ap_slotmem_instance_t *mem; > >- if (*mem) { >- ap_slotmem_instance_t *next = *mem; >- while (next) { >- if (AP_SLOTMEM_IS_PERSIST(next)) { >- store_slotmem(next); >+ /* When in startup/pre-config's cleanup, the retained data and global pool >+ * are not used yet, but the SHMs contents were untouched hence they don't >+ * need to be persisted, simply unlink them. >+ * Otherwise when restarting or stopping we want to flush persisted data, >+ * and in the stopping/exiting case we also want to unlink the SHMs. >+ */ >+ for (mem = globallistmem; mem; mem = mem->next) { >+ int unlink; >+ if (is_startup) { >+ unlink = mem->fbased; >+ } >+ else { >+ if (AP_SLOTMEM_IS_PERSIST(mem)) { >+ store_slotmem(mem); > } >- apr_shm_destroy((apr_shm_t *)next->shm); >- if (next->fbased) { >- apr_shm_remove(next->name, next->gpool); >- apr_file_remove(next->name, next->gpool); >- } >- next = next->next; >+ unlink = is_exiting; > } >+ if (unlink) { >+ /* Some systems may require the descriptor to be closed before >+ * unlink, thus call destroy() first. >+ */ >+ apr_shm_destroy(mem->shm); >+ apr_shm_remove(mem->name, mem->pool); >+ } > } >- /* apr_pool_destroy(gpool); */ >+ >+ if (is_exiting) { >+ *retained_globallistmem = NULL; >+ } >+ else if (!is_startup) { >+ *retained_globallistmem = globallistmem; >+ } > globallistmem = NULL; >+ > return APR_SUCCESS; > } > >@@ -309,18 +331,43 @@ static apr_status_t slotmem_doall(ap_slotmem_insta > > ptr = (char *)mem->base; > inuse = mem->inuse; >- for (i = 0; i < mem->desc.num; i++, inuse++) { >- if (!AP_SLOTMEM_IS_PREGRAB(mem) || >- (AP_SLOTMEM_IS_PREGRAB(mem) && *inuse)) { >+ for (i = 0; i < mem->desc->num; i++, inuse++) { >+ if (!AP_SLOTMEM_IS_PREGRAB(mem) || *inuse) { > retval = func((void *) ptr, data, pool); > if (retval != APR_SUCCESS) > break; > } >- ptr += mem->desc.size; >+ ptr += mem->desc->size; > } > return retval; > } > >+static int check_slotmem(ap_slotmem_instance_t *mem, apr_size_t size, >+ apr_size_t item_size, unsigned int item_num) >+{ >+ sharedslotdesc_t *desc; >+ >+ /* check size */ >+ if (apr_shm_size_get(mem->shm) != size) { >+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02599) >+ "existing shared memory for %s could not be used " >+ "(failed size check)", >+ mem->name); >+ return 0; >+ } >+ >+ desc = apr_shm_baseaddr_get(mem->shm); >+ if (desc->size != item_size || desc->num != item_num) { >+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02600) >+ "existing shared memory for %s could not be used " >+ "(failed contents check)", >+ mem->name); >+ return 0; >+ } >+ >+ return 1; >+} >+ > static apr_status_t slotmem_create(ap_slotmem_instance_t **new, > const char *name, apr_size_t item_size, > unsigned int item_num, >@@ -329,7 +376,7 @@ static apr_status_t slotmem_create(ap_slotmem_inst > int fbased = 1; > int restored = 0; > char *ptr; >- sharedslotdesc_t desc; >+ sharedslotdesc_t *desc; > ap_slotmem_instance_t *res; > ap_slotmem_instance_t *next = globallistmem; > const char *fname, *pname = NULL; >@@ -339,17 +386,33 @@ static apr_status_t slotmem_create(ap_slotmem_inst > (item_num * sizeof(char)) + basesize; > int persist = (type & AP_SLOTMEM_TYPE_PERSIST) != 0; > apr_status_t rv; >+ apr_pool_t *p; > >- if (gpool == NULL) { >- return APR_ENOSHMAVAIL; >- } >+ *new = NULL; >+ > if (slotmem_filenames(pool, name, &fname, persist ? &pname : NULL)) { > /* first try to attach to existing slotmem */ > if (next) { >+ ap_slotmem_instance_t *prev = NULL; > for (;;) { > if (strcmp(next->name, fname) == 0) { >+ *new = next; /* either returned here or reused finally */ >+ if (!check_slotmem(next, size, item_size, item_num)) { >+ apr_shm_destroy(next->shm); >+ next = next->next; >+ if (prev) { >+ prev->next = next; >+ } >+ else { >+ globallistmem = next; >+ } >+ if (next) { >+ continue; >+ } >+ next = prev; >+ break; >+ } > /* we already have it */ >- *new = next; > ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02603) > "create found %s in global list", fname); > return APR_SUCCESS; >@@ -357,6 +420,7 @@ static apr_status_t slotmem_create(ap_slotmem_inst > if (!next->next) { > break; > } >+ prev = next; > next = next->next; > } > } >@@ -372,43 +436,14 @@ static apr_status_t slotmem_create(ap_slotmem_inst > ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02300) > "create %s: %"APR_SIZE_T_FMT"/%u", fname, item_size, > item_num); >- if (fbased) { >- rv = apr_shm_attach(&shm, fname, gpool); >- } >- else { >- rv = APR_EINVAL; >- } >- if (rv == APR_SUCCESS) { >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02598) >- "apr_shm_attach() succeeded"); > >- /* check size */ >- if (apr_shm_size_get(shm) != size) { >- apr_shm_detach(shm); >- ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02599) >- "existing shared memory for %s could not be used (failed size check)", >- fname); >- return APR_EINVAL; >- } >- ptr = (char *)apr_shm_baseaddr_get(shm); >- memcpy(&desc, ptr, sizeof(desc)); >- if (desc.size != item_size || desc.num != item_num) { >- apr_shm_detach(shm); >- ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02600) >- "existing shared memory for %s could not be used (failed contents check)", >- fname); >- return APR_EINVAL; >- } >- ptr += AP_SLOTMEM_OFFSET; >- } >- else { >- apr_size_t dsize = size - AP_SLOTMEM_OFFSET; >+ { > if (fbased) { >- apr_shm_remove(fname, gpool); >+ apr_shm_remove(fname, pool); > rv = apr_shm_create(&shm, size, fname, gpool); > } > else { >- rv = apr_shm_create(&shm, size, NULL, gpool); >+ rv = apr_shm_create(&shm, size, NULL, pool); > } > ap_log_error(APLOG_MARK, rv == APR_SUCCESS ? APLOG_DEBUG : APLOG_ERR, > rv, ap_server_conf, APLOGNO(02611) >@@ -418,57 +453,67 @@ static apr_status_t slotmem_create(ap_slotmem_inst > if (rv != APR_SUCCESS) { > return rv; > } >- ptr = (char *)apr_shm_baseaddr_get(shm); >- desc.size = item_size; >- desc.num = item_num; >- desc.type = type; >- memcpy(ptr, &desc, sizeof(desc)); >- ptr += AP_SLOTMEM_OFFSET; >- memset(ptr, 0, dsize); >+ >+ desc = (sharedslotdesc_t *)apr_shm_baseaddr_get(shm); >+ memset(desc, 0, size); >+ desc->size = item_size; >+ desc->num = item_num; >+ desc->type = type; >+ > /* > * TODO: Error check the below... What error makes > * sense if the restore fails? Any? >+ * For now, we continue with a fresh new slotmem, >+ * but NOTICE in the log. > */ > if (persist) { >- rv = restore_slotmem(ptr, pname, dsize, pool); >+ rv = restore_slotmem(desc, pname, size, pool); > if (rv == APR_SUCCESS) { > restored = 1; > } > else { > /* just in case, re-zero */ >- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, >+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, > APLOGNO(02554) "could not restore %s", fname); >- memset(ptr, 0, dsize); >+ memset((char *)desc + AP_SLOTMEM_OFFSET, 0, >+ size - AP_SLOTMEM_OFFSET); > } > } > } > >- /* For the chained slotmem stuff */ >- res = (ap_slotmem_instance_t *) apr_pcalloc(gpool, >- sizeof(ap_slotmem_instance_t)); >- res->name = apr_pstrdup(gpool, fname); >- res->pname = apr_pstrdup(gpool, pname); >+ p = fbased ? gpool : pool; >+ ptr = (char *)desc + AP_SLOTMEM_OFFSET; >+ >+ /* For the chained slotmem stuff (*new may be reused from above) */ >+ res = *new; >+ if (res == NULL) { >+ res = apr_pcalloc(p, sizeof(ap_slotmem_instance_t)); >+ res->name = apr_pstrdup(p, fname); >+ res->pname = apr_pstrdup(p, pname); >+ *new = res; >+ } > res->fbased = fbased; > res->shm = shm; >+ res->persist = (void *)ptr; > res->num_free = (unsigned int *)ptr; >+ ptr += AP_UNSIGNEDINT_OFFSET; > if (!restored) { > *res->num_free = item_num; > } >- res->persist = (void *)ptr; >- ptr += AP_UNSIGNEDINT_OFFSET; > res->base = (void *)ptr; > res->desc = desc; >- res->gpool = gpool; >+ res->pool = pool; > res->next = NULL; > res->inuse = ptr + basesize; >- if (globallistmem == NULL) { >- globallistmem = res; >+ if (fbased) { >+ if (globallistmem == NULL) { >+ globallistmem = res; >+ } >+ else { >+ next->next = res; >+ } > } >- else { >- next->next = res; >- } > >- *new = res; > return APR_SUCCESS; > } > >@@ -480,14 +525,11 @@ static apr_status_t slotmem_attach(ap_slotmem_inst > char *ptr; > ap_slotmem_instance_t *res; > ap_slotmem_instance_t *next = globallistmem; >- sharedslotdesc_t desc; >+ sharedslotdesc_t *desc; > const char *fname; > apr_shm_t *shm; > apr_status_t rv; > >- if (gpool == NULL) { >- return APR_ENOSHMAVAIL; >- } > if (!slotmem_filenames(pool, name, &fname, NULL)) { > return APR_ENOSHMAVAIL; > } >@@ -501,8 +543,8 @@ static apr_status_t slotmem_attach(ap_slotmem_inst > if (strcmp(next->name, fname) == 0) { > /* we already have it */ > *new = next; >- *item_size = next->desc.size; >- *item_num = next->desc.num; >+ *item_size = next->desc->size; >+ *item_num = next->desc->num; > ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, > APLOGNO(02302) > "attach found %s: %"APR_SIZE_T_FMT"/%u", fname, >@@ -517,40 +559,32 @@ static apr_status_t slotmem_attach(ap_slotmem_inst > } > > /* next try to attach to existing shared memory */ >- rv = apr_shm_attach(&shm, fname, gpool); >+ rv = apr_shm_attach(&shm, fname, pool); > if (rv != APR_SUCCESS) { > return rv; > } > > /* Read the description of the slotmem */ >- ptr = (char *)apr_shm_baseaddr_get(shm); >- memcpy(&desc, ptr, sizeof(desc)); >- ptr += AP_SLOTMEM_OFFSET; >+ desc = (sharedslotdesc_t *)apr_shm_baseaddr_get(shm); >+ ptr = (char *)desc + AP_SLOTMEM_OFFSET; > > /* For the chained slotmem stuff */ >- res = (ap_slotmem_instance_t *) apr_pcalloc(gpool, >- sizeof(ap_slotmem_instance_t)); >- res->name = apr_pstrdup(gpool, fname); >+ res = apr_pcalloc(pool, sizeof(ap_slotmem_instance_t)); >+ res->name = apr_pstrdup(pool, fname); > res->fbased = 1; > res->shm = shm; >+ res->persist = (void *)ptr; > res->num_free = (unsigned int *)ptr; >- res->persist = (void *)ptr; > ptr += AP_UNSIGNEDINT_OFFSET; > res->base = (void *)ptr; > res->desc = desc; >- res->gpool = gpool; >- res->inuse = ptr + (desc.size * desc.num); >+ res->pool = pool; >+ res->inuse = ptr + (desc->size * desc->num); > res->next = NULL; >- if (globallistmem == NULL) { >- globallistmem = res; >- } >- else { >- next->next = res; >- } > > *new = res; >- *item_size = desc.size; >- *item_num = desc.num; >+ *item_size = desc->size; >+ *item_num = desc->num; > ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, > APLOGNO(02303) > "attach found %s: %"APR_SIZE_T_FMT"/%u", fname, >@@ -566,11 +600,11 @@ static apr_status_t slotmem_dptr(ap_slotmem_instan > if (!slot) { > return APR_ENOSHMAVAIL; > } >- if (id >= slot->desc.num) { >+ if (id >= slot->desc->num) { > return APR_EINVAL; > } > >- ptr = (char *)slot->base + slot->desc.size * id; >+ ptr = (char *)slot->base + slot->desc->size * id; > if (!ptr) { > return APR_ENOSHMAVAIL; > } >@@ -590,7 +624,7 @@ static apr_status_t slotmem_get(ap_slotmem_instanc > } > > inuse = slot->inuse + id; >- if (id >= slot->desc.num) { >+ if (id >= slot->desc->num) { > return APR_EINVAL; > } > if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) { >@@ -617,7 +651,7 @@ static apr_status_t slotmem_put(ap_slotmem_instanc > } > > inuse = slot->inuse + id; >- if (id >= slot->desc.num) { >+ if (id >= slot->desc->num) { > return APR_EINVAL; > } > if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) { >@@ -634,7 +668,7 @@ static apr_status_t slotmem_put(ap_slotmem_instanc > > static unsigned int slotmem_num_slots(ap_slotmem_instance_t *slot) > { >- return slot->desc.num; >+ return slot->desc->num; > } > > static unsigned int slotmem_num_free_slots(ap_slotmem_instance_t *slot) >@@ -644,7 +678,7 @@ static unsigned int slotmem_num_free_slots(ap_slot > else { > unsigned int i, counter=0; > char *inuse = slot->inuse; >- for (i=0; i<slot->desc.num; i++, inuse++) { >+ for (i=0; i<slot->desc->num; i++, inuse++) { > if (!*inuse) > counter++; > } >@@ -654,7 +688,7 @@ static unsigned int slotmem_num_free_slots(ap_slot > > static apr_size_t slotmem_slot_size(ap_slotmem_instance_t *slot) > { >- return slot->desc.size; >+ return slot->desc->size; > } > > static apr_status_t slotmem_grab(ap_slotmem_instance_t *slot, unsigned int *id) >@@ -668,12 +702,12 @@ static apr_status_t slotmem_grab(ap_slotmem_instan > > inuse = slot->inuse; > >- for (i = 0; i < slot->desc.num; i++, inuse++) { >+ for (i = 0; i < slot->desc->num; i++, inuse++) { > if (!*inuse) { > break; > } > } >- if (i >= slot->desc.num) { >+ if (i >= slot->desc->num) { > ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02293) > "slotmem(%s) grab failed. Num %u/num_free %u", > slot->name, slotmem_num_slots(slot), >@@ -694,7 +728,7 @@ static apr_status_t slotmem_fgrab(ap_slotmem_insta > return APR_ENOSHMAVAIL; > } > >- if (id >= slot->desc.num) { >+ if (id >= slot->desc->num) { > ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02397) > "slotmem(%s) fgrab failed. Num %u/num_free %u", > slot->name, slotmem_num_slots(slot), >@@ -721,12 +755,12 @@ static apr_status_t slotmem_release(ap_slotmem_ins > > inuse = slot->inuse; > >- if (id >= slot->desc.num || !inuse[id] ) { >+ if (id >= slot->desc->num || !inuse[id] ) { > ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02294) > "slotmem(%s) release failed. Num %u/inuse[%u] %d", > slot->name, slotmem_num_slots(slot), > id, (int)inuse[id]); >- if (id >= slot->desc.num) { >+ if (id >= slot->desc->num) { > return APR_EINVAL; > } else { > return APR_NOTFOUND; >@@ -759,42 +793,43 @@ static const ap_slotmem_provider_t *slotmem_shm_ge > return (&storage); > } > >-/* initialise the global pool */ >-static void slotmem_shm_initgpool(apr_pool_t *p) >+/* Initialize or reuse the retained slotmems list, and register the >+ * cleanup to make sure the persisted SHMs are stored and the retained >+ * data are up to date on next restart/stop. >+ */ >+static int pre_config(apr_pool_t *pconf, apr_pool_t *plog, >+ apr_pool_t *ptemp) > { >- gpool = p; >-} >+ void *is_startup = NULL; >+ const char *retained_key = "mod_slotmem_shm"; > >-/* Add the pool_clean routine */ >-static void slotmem_shm_initialize_cleanup(apr_pool_t *p) >-{ >- apr_pool_cleanup_register(p, &globallistmem, cleanup_slotmem, >+ retained_globallistmem = ap_retained_data_get(retained_key); >+ if (!retained_globallistmem) { >+ retained_globallistmem = >+ ap_retained_data_create(retained_key, >+ sizeof *retained_globallistmem); >+ } >+ globallistmem = *retained_globallistmem; >+ >+ if (ap_state_query(AP_SQ_MAIN_STATE) != AP_SQ_MS_CREATE_PRE_CONFIG) { >+ gpool = ap_pglobal; >+ } >+ else { >+ is_startup = (void *)1; >+ gpool = pconf; >+ } >+ >+ apr_pool_cleanup_register(pconf, is_startup, cleanup_slotmem, > apr_pool_cleanup_null); >-} > >-/* >- * Make sure the shared memory is cleaned >- */ >-static int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, >- server_rec *s) >-{ >- slotmem_shm_initialize_cleanup(p); > return OK; > } > >-static int pre_config(apr_pool_t *p, apr_pool_t *plog, >- apr_pool_t *ptemp) >-{ >- slotmem_shm_initgpool(p); >- return OK; >-} >- > static void ap_slotmem_shm_register_hook(apr_pool_t *p) > { > const ap_slotmem_provider_t *storage = slotmem_shm_getstorage(); > ap_register_provider(p, AP_SLOTMEM_PROVIDER_GROUP, "shm", > AP_SLOTMEM_PROVIDER_VERSION, storage); >- ap_hook_post_config(post_config, NULL, NULL, APR_HOOK_LAST); > ap_hook_pre_config(pre_config, NULL, NULL, APR_HOOK_MIDDLE); > } > >Index: . >=================================================================== >--- . (revision 1823575) >+++ . (working copy) > >Property changes on: . >___________________________________________________________________ >Modified: svn:mergeinfo >## -0,0 +0,1 ## > Merged /httpd/httpd/trunk:r1822509,1822511,1823412,1823415-1823416,1823564,1823572,1823575
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 62044
:
35698
|
35702
|
35710
| 35723