On Sat, Jan 27, 2018 at 4:39 PM, Yann Ylavic <[email protected]> wrote:
> On Sat, Jan 27, 2018 at 3:14 PM, Yann Ylavic <[email protected]> wrote:
>>
>> So I wonder if we'd better:
>> 1. have a constant file name (no generation suffix) for all systems,
>> 2. not unlink/remove the SHM file on pconf cleanup,
>> 2'. eventually unlink the ones unused in ++generation (e.g. retained
>> global list),
>> 3. unlink all on pglobal cleanup.
>>
>> Now we'd have a working shm_attach() not only for persisted slotmems,
>> while shm_create() would only be called for new SHMs which we know can
>> be pre-removed (to work around crashes leaving them registered
>> somewhere).
>> Also, if attach succeeds on startup (first generation) but the SHM is
>> not persisted (an old crash still), we can possibly pass the sizes
>> checks and re-create the SHM regardless.
>>
>> WDYT?
>
> Something like the attached patch (it talks better sometimes...).
> Not even tested of course :)
Oops, more than needed in there, here is the good one.
Index: modules/slotmem/mod_slotmem_shm.c
===================================================================
--- modules/slotmem/mod_slotmem_shm.c (revision 1821739)
+++ modules/slotmem/mod_slotmem_shm.c (working copy)
@@ -47,7 +47,7 @@ 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 working pool */
char *inuse; /* in-use flag table*/
unsigned int *num_free; /* slot free count for this instance */
void *persist; /* persist dataset start */
@@ -64,7 +64,8 @@ struct ap_slotmem_instance_t {
*/
/* 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-"
@@ -191,11 +192,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;
@@ -212,7 +213,7 @@ static void store_slotmem(ap_slotmem_instance_t *s
}
apr_file_close(fp);
if (rv != APR_SUCCESS) {
- apr_file_remove(storename, slotmem->gpool);
+ apr_file_remove(storename, slotmem->pool);
}
}
}
@@ -271,26 +272,35 @@ static apr_status_t restore_slotmem(void *ptr, con
return rv;
}
+static apr_status_t global_cleanup_slotmem(void *param)
+{
+ AP_DEBUG_ASSERT(retained_globallistmem != NULL);
+ *retained_globallistmem = NULL;
+
+ while (globallistmem) {
+ if (globallistmem->fbased) {
+ apr_shm_destroy(globallistmem->shm);
+ apr_shm_remove(globallistmem->name, globallistmem->pool);
+ apr_file_remove(globallistmem->name, globallistmem->pool);
+ }
+ globallistmem = globallistmem->next;
+ }
+
+ return APR_SUCCESS;
+}
+
static apr_status_t cleanup_slotmem(void *param)
{
- ap_slotmem_instance_t **mem = param;
+ AP_DEBUG_ASSERT(retained_globallistmem != NULL);
+ *retained_globallistmem = globallistmem;
- if (*mem) {
- ap_slotmem_instance_t *next = *mem;
- while (next) {
- if (AP_SLOTMEM_IS_PERSIST(next)) {
- store_slotmem(next);
- }
- 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;
+ while (globallistmem) {
+ if (AP_SLOTMEM_IS_PERSIST(globallistmem)) {
+ store_slotmem(globallistmem);
}
+ globallistmem = globallistmem->next;
}
- /* apr_pool_destroy(gpool); */
- globallistmem = NULL;
+
return APR_SUCCESS;
}
@@ -338,11 +348,11 @@ static apr_status_t slotmem_create(ap_slotmem_inst
apr_size_t size = AP_SLOTMEM_OFFSET + AP_UNSIGNEDINT_OFFSET +
(item_num * sizeof(char)) + basesize;
int persist = (type & AP_SLOTMEM_TYPE_PERSIST) != 0;
+ int generation = 0;
apr_status_t rv;
- if (gpool == NULL) {
- return APR_ENOSHMAVAIL;
- }
+ ap_mpm_query(AP_MPMQ_GENERATION, &generation);
+
if (slotmem_filenames(pool, name, &fname, persist ? &pname : NULL)) {
/* first try to attach to existing slotmem */
if (next) {
@@ -372,13 +382,13 @@ 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);
+ if (fbased && generation > 1) {
+ rv = apr_shm_attach(&shm, fname, pool);
}
else {
rv = APR_EINVAL;
}
- if (rv == APR_SUCCESS) {
+ if (rv == APR_SUCCESS && persist) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02598)
"apr_shm_attach() succeeded");
@@ -401,10 +411,10 @@ static apr_status_t slotmem_create(ap_slotmem_inst
}
ptr += AP_SLOTMEM_OFFSET;
}
- else {
+ else if (rv != APR_SUCCESS) {
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 {
@@ -444,8 +454,7 @@ static apr_status_t slotmem_create(ap_slotmem_inst
}
/* For the chained slotmem stuff */
- res = (ap_slotmem_instance_t *) apr_pcalloc(gpool,
- sizeof(ap_slotmem_instance_t));
+ res = apr_pcalloc(gpool, sizeof(ap_slotmem_instance_t));
res->name = apr_pstrdup(gpool, fname);
res->pname = apr_pstrdup(gpool, pname);
res->fbased = fbased;
@@ -458,7 +467,7 @@ static apr_status_t slotmem_create(ap_slotmem_inst
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) {
@@ -485,9 +494,6 @@ static apr_status_t slotmem_attach(ap_slotmem_inst
apr_shm_t *shm;
apr_status_t rv;
- if (gpool == NULL) {
- return APR_ENOSHMAVAIL;
- }
if (!slotmem_filenames(pool, name, &fname, NULL)) {
return APR_ENOSHMAVAIL;
}
@@ -528,8 +534,7 @@ static apr_status_t slotmem_attach(ap_slotmem_inst
ptr += AP_SLOTMEM_OFFSET;
/* For the chained slotmem stuff */
- res = (ap_slotmem_instance_t *) apr_pcalloc(gpool,
- sizeof(ap_slotmem_instance_t));
+ res = apr_pcalloc(gpool, sizeof(ap_slotmem_instance_t));
res->name = apr_pstrdup(gpool, fname);
res->fbased = 1;
res->shm = shm;
@@ -538,7 +543,7 @@ static apr_status_t slotmem_attach(ap_slotmem_inst
ptr += AP_UNSIGNEDINT_OFFSET;
res->base = (void *)ptr;
res->desc = desc;
- res->gpool = gpool;
+ res->pool = pool;
res->inuse = ptr + (desc.size * desc.num);
res->next = NULL;
if (globallistmem == NULL) {
@@ -760,18 +765,23 @@ static const ap_slotmem_provider_t *slotmem_shm_ge
}
/* initialise the global pool */
-static void slotmem_shm_initgpool(apr_pool_t *p)
+static int pre_config(apr_pool_t *p, apr_pool_t *plog,
+ apr_pool_t *ptemp)
{
- gpool = p;
+ const char *retained_key = "mod_slotmem_shm";
+ retained_globallistmem = ap_retained_data_get(retained_key);
+ if (!retained_globallistmem) {
+ retained_globallistmem =
+ ap_retained_data_create(retained_key,
+ sizeof *retained_globallistmem);
+ apr_pool_cleanup_register(ap_pglobal, NULL, global_cleanup_slotmem,
+ apr_pool_cleanup_null);
+ }
+ globallistmem = *retained_globallistmem;
+ gpool = ap_pglobal;
+ return OK;
}
-/* Add the pool_clean routine */
-static void slotmem_shm_initialize_cleanup(apr_pool_t *p)
-{
- apr_pool_cleanup_register(p, &globallistmem, cleanup_slotmem,
- apr_pool_cleanup_null);
-}
-
/*
* Make sure the shared memory is cleaned
*/
@@ -778,17 +788,11 @@ static const ap_slotmem_provider_t *slotmem_shm_ge
static int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
server_rec *s)
{
- slotmem_shm_initialize_cleanup(p);
+ apr_pool_cleanup_register(p, NULL, cleanup_slotmem,
+ apr_pool_cleanup_null);
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();