]> granicus.if.org Git - apache/commitdiff
Restore mod_slotmem_shm from 2.4.29.
authorYann Ylavic <ylavic@apache.org>
Fri, 18 May 2018 16:22:21 +0000 (16:22 +0000)
committerYann Ylavic <ylavic@apache.org>
Fri, 18 May 2018 16:22:21 +0000 (16:22 +0000)
Will restart from there to really fix PR 62308 (and PR 62044 still).

This effectively reverts:
- r1831394,
- r1830800,
- r1826970,
- r1826845,
- r1823572,
- r1823416,
- r1823415,
- r1823412,
- r1822511,
- r1822509.

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

CHANGES
modules/slotmem/mod_slotmem_shm.c

diff --git a/CHANGES b/CHANGES
index 71343305b9d6289b687f6d4101c0ae52db4a5198..acb23ce16a0be41736f7c3705cc8d32dcdb3cf31 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -11,11 +11,6 @@ Changes with Apache 2.5.1
      PKCS#11 OpenSSL engine.  [Anderson Sasaki <ansasaki redhat.com>,
      Joe Orton]
 
-  *) mod_slomem_shm: Handle a generation number when the slotmem size changes,
-     modifying the number of proxy balancers or balancer members on restart
-     could have prevented the server to load, notably on Windows. PR 62308.
-     [Yann Ylavic]
-
   *) mod_proxy_html: Fix variable interpolation and memory allocation failure
      in ProxyHTMLURLMap.  [Ewald Dieterich <ewald mailbox.org>]
 
index 8d6bc48fe837bc6e46db4a4b7873add7116d6966..04258def0ee97c609aec2f4a1d11d0769e2d6639 100644 (file)
 
 #include "httpd.h"
 #include "http_main.h"
-#include "http_core.h"
-#include "ap_mpm.h"
+#include "ap_mpm.h" /* for ap_mpm_query() */
 
-#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 {
@@ -43,43 +42,60 @@ typedef struct {
 #define AP_UNSIGNEDINT_OFFSET (APR_ALIGN_DEFAULT(sizeof(unsigned int)))
 
 struct ap_slotmem_instance_t {
-    char                 *name;       /* file based SHM name (immutable) */
-    char                 *fname;      /* file based SHM path/name */
+    char                 *name;       /* file based SHM path/name */
     char                 *pname;      /* persisted file path/name */
     int                  fbased;      /* filebased? */
     void                 *shm;        /* ptr to memory segment (apr_shm_t *) */
     void                 *base;       /* data set start */
-    apr_pool_t           *pool;       /* per segment pool (generation cleared) */
+    apr_pool_t           *gpool;      /* per segment global pool */
     char                 *inuse;      /* in-use flag table*/
     unsigned int         *num_free;   /* slot free count for this instance */
     void                 *persist;    /* persist dataset start */
-    const sharedslotdesc_t *desc;     /* per slot desc */
+    sharedslotdesc_t     desc;        /* per slot desc */
     struct ap_slotmem_instance_t  *next;       /* location of next allocated segment */
 };
 
 /*
- * Layout for SHM and persited file :
- *
- *   +-------------------------------------------------------------+~>
- *   | desc | num_free | base (slots) | inuse (array) | md5 | desc | compat..
- *   +------+-----------------------------------------+------------+~>
- *   ^      ^                                         ^    \ /     ^   :
- *   |______|_____________ SHM (mem->@) ______________|     | _____|__/
- *          |                                               |/     |
- *          |                                         ^     v      |
- *          |_____________________ File (mem->persist +  [meta]) __|
+ * Memory layout:
+ *     sharedslotdesc_t | num_free | slots | isuse array |
+ *                      ^          ^
+ *                      |          . base
+ *                      . persist (also num_free)
  */
 
-
 /* global pool and list of slotmem we are handling */
-static struct ap_slotmem_instance_t *globallistmem = NULL,
-                                   **retained_globallistmem = NULL;
+static struct ap_slotmem_instance_t *globallistmem = NULL;
 static apr_pool_t *gpool = NULL;
 
 #define DEFAULT_SLOTMEM_PREFIX "slotmem-shm-"
 #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.
@@ -97,9 +113,18 @@ 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 {
@@ -110,6 +135,17 @@ 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);
@@ -134,7 +170,7 @@ static void slotmem_clearinuse(ap_slotmem_instance_t *slot)
     
     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)++;
@@ -155,11 +191,11 @@ static void store_slotmem(ap_slotmem_instance_t *slotmem)
 
     if (storename) {
         rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE,
-                           APR_OS_DEFAULT, slotmem->pool);
+                           APR_OS_DEFAULT, slotmem->gpool);
         if (APR_STATUS_IS_EEXIST(rv)) {
-            apr_file_remove(storename, slotmem->pool);
+            apr_file_remove(storename, slotmem->gpool);
             rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE,
-                               APR_OS_DEFAULT, slotmem->pool);
+                               APR_OS_DEFAULT, slotmem->gpool);
         }
         if (rv != APR_SUCCESS) {
             return;
@@ -167,36 +203,28 @@ static void store_slotmem(ap_slotmem_instance_t *slotmem)
         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->pool);
+            apr_file_remove(storename, slotmem->gpool);
         }
     }
 }
 
-static apr_status_t restore_slotmem(sharedslotdesc_t *desc,
-                                    const char *storename, apr_size_t size,
-                                    apr_pool_t *pool)
+static apr_status_t restore_slotmem(void *ptr, const char *storename,
+                                    apr_size_t size, apr_pool_t *pool)
 {
     apr_file_t *fp;
-    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;
+    apr_size_t nbytes = size;
+    apr_status_t rv = APR_SUCCESS;
     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);
@@ -206,7 +234,7 @@ static apr_status_t restore_slotmem(sharedslotdesc_t *desc,
                            pool);
         if (rv == APR_SUCCESS) {
             rv = apr_file_read(fp, ptr, &nbytes);
-            if ((rv == APR_SUCCESS || rv == APR_EOF) && nbytes == dsize) {
+            if ((rv == APR_SUCCESS || rv == APR_EOF) && nbytes == size) {
                 rv = APR_SUCCESS;   /* for successful return @ EOF */
                 /*
                  * if at EOF, don't bother checking md5
@@ -215,60 +243,27 @@ static apr_status_t restore_slotmem(sharedslotdesc_t *desc,
                 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) {
+                    if ((rv == APR_SUCCESS || rv == APR_EOF) &&
+                        ds == APR_MD5_DIGESTSIZE) {
+                        rv = APR_SUCCESS;
                         apr_md5(digest2, ptr, nbytes);
                         if (memcmp(digest, digest2, APR_MD5_DIGESTSIZE)) {
-                            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;
-                            }
+                            ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
+                                         APLOGNO(02551) "bad md5 match");
+                            rv = APR_EGENERAL;
                         }
-                        else {
-                            rv = APR_EOF;
-                        }
-                    }
-                    else if (rv == APR_SUCCESS || rv == APR_EOF) {
-                        rv = APR_INCOMPLETE;
                     }
                 }
                 else {
-                    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;
+                    ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
+                                 APLOGNO(02552) "at EOF... bypassing md5 match check (old persist file?)");
                 }
             }
-            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");
+            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;
             }
             apr_file_close(fp);
         }
@@ -276,53 +271,26 @@ static apr_status_t restore_slotmem(sharedslotdesc_t *desc,
     return rv;
 }
 
-/*
- * Whether the module is called from a MPM that re-enter main() and
- * pre/post_config phases.
- */
-static APR_INLINE int is_child_process(void)
+static apr_status_t cleanup_slotmem(void *param)
 {
-#ifdef WIN32
-    return getenv("AP_PARENT_PID") != NULL;
-#else
-    return 0;
-#endif
-}
+    ap_slotmem_instance_t **mem = param;
 
-static apr_status_t cleanup_slotmem(void *nil)
-{
-    int is_exiting = (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_EXITING);
-    int is_child = is_child_process();
-    ap_slotmem_instance_t *mem;
-
-    /* When restarting or stopping we want to flush persisted data, and in
-     * the stopping case we also want to unlink the SHMs. A MPM winnt child
-     * process is always exiting here, we don't want it to care about persisted
-     * data but it still has to (try to) cleanup SHMs since it may be the last
-     * one to use them, and Windows prevent anything but the last user to
-     * effectively destroy/remove an open SHM/file.
-     */
-    for (mem = globallistmem; mem; mem = mem->next) {
-        if (AP_SLOTMEM_IS_PERSIST(mem) && !is_child) {
-            store_slotmem(mem);
-        }
-        if (is_exiting) {
-            /* Some systems require the descriptor to be closed before
-             * unlinked, thus call destroy() first.
-             */
-            apr_shm_destroy(mem->shm);
-            apr_shm_remove(mem->fname, mem->pool);
+    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;
         }
     }
-
-    if (is_exiting) {
-        *retained_globallistmem = NULL;
-    }
-    else {
-        /* Restarting, save list for next run */
-        *retained_globallistmem = globallistmem;
-    }
-
+    /* apr_pool_destroy(gpool); */
+    globallistmem = NULL;
     return APR_SUCCESS;
 }
 
@@ -341,66 +309,18 @@ static apr_status_t slotmem_doall(ap_slotmem_instance_t *mem,
 
     ptr = (char *)mem->base;
     inuse = mem->inuse;
-    for (i = 0; i < mem->desc->num; i++, inuse++) {
-        if (!AP_SLOTMEM_IS_PREGRAB(mem) || *inuse) {
+    for (i = 0; i < mem->desc.num; i++, inuse++) {
+        if (!AP_SLOTMEM_IS_PREGRAB(mem) ||
+           (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_INFO, 0, ap_server_conf, APLOGNO(02599)
-                     "existing shared memory for %s could not be reused "
-                     "(failed size check)",
-                     mem->fname);
-        return 0;
-    }
-
-    desc = apr_shm_baseaddr_get(mem->shm);
-    if (desc->size != item_size || desc->num != item_num) {
-        ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(02600)
-                     "existing shared memory for %s could not be reused "
-                     "(failed contents check)",
-                     mem->fname);
-        return 0;
-    }
-
-    return 1;
-}
-
-static apr_status_t slotmem_attach_shm(apr_shm_t **shm, const char **fname,
-                                       apr_uint32_t num, apr_pool_t *pool)
-{
-    char *name = NULL;
-    apr_size_t size = 0, offset = 0;
-
-    for (; num; --num) {
-        if (!name) {
-            name = apr_psprintf(pool, "%s.%u", *fname, APR_UINT32_MAX);
-            offset = strlen(*fname) + 1;
-            size = offset + strlen(name + offset) + 1;
-        }
-        apr_snprintf(name + offset, size - offset, "%u", num);
-
-        if (apr_shm_attach(shm, name, pool) == APR_SUCCESS) {
-            *fname = name;
-            return APR_SUCCESS;
-        }
-    }
-
-    return apr_shm_attach(shm, *fname, pool);
-}
-
 static apr_status_t slotmem_create(ap_slotmem_instance_t **new,
                                    const char *name, apr_size_t item_size,
                                    unsigned int item_num,
@@ -409,7 +329,7 @@ static apr_status_t slotmem_create(ap_slotmem_instance_t **new,
     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;
@@ -418,60 +338,30 @@ static apr_status_t slotmem_create(ap_slotmem_instance_t **new,
     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;
-    apr_pool_t *p;
-
-    *new = NULL;
-    ap_mpm_query(AP_MPMQ_GENERATION, &generation);
 
+    if (gpool == NULL) {
+        return APR_ENOSHMAVAIL;
+    }
     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, name) == 0) {
-                    *new = next; /* either returned here or reused finally */
-                    if (!check_slotmem(next, size, item_size, item_num)) {
-                        /* Can't reuse this SHM, a new one is needed with its
-                         * own filename (including generation number) because
-                         * the previous one may still be used by the previous
-                         * generation. Persisted file (if any) can't be reused
-                         * either.
-                         */
-                        apr_shm_destroy(next->shm);
-                        apr_shm_remove(next->fname, pool);
-                        fname = apr_psprintf(pool, "%s.%u", fname,
-                                             (apr_uint32_t)generation);
-                        persist = 0;
-
-                        next = next->next;
-                        if (prev) {
-                            prev->next = next;
-                        }
-                        else {
-                            globallistmem = next;
-                        }
-                        if (next) {
-                            continue;
-                        }
-                        next = prev;
-                        break;
-                    }
+                if (strcmp(next->name, fname) == 0) {
                     /* 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", next->fname);
+                                 "create found %s in global list", fname);
                     return APR_SUCCESS;
                 }
                 if (!next->next) {
                      break;
                 }
-                prev = next;
                 next = next->next;
             }
         }
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02602)
-                     "create didn't find %s in global list", name);
+                     "create didn't find %s in global list", fname);
     }
     else {
         fbased = 0;
@@ -480,95 +370,105 @@ static apr_status_t slotmem_create(ap_slotmem_instance_t **new,
 
     /* first try to attach to existing shared memory */
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02300)
-                 "create %s: %"APR_SIZE_T_FMT"/%u", name, item_size, item_num);
-
-    {
+                 "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) {
-            /* For MPMs that run pre/post_config() phases in both the parent
-             * and children processes (e.g. winnt), SHMs created by the
-             * parent exist in the children already; attach them.
-             */
-            if (is_child_process()) {
-                rv = slotmem_attach_shm(&shm, &fname, generation, gpool);
-            }
-            else {
-                apr_shm_remove(fname, pool);
-                rv = apr_shm_create(&shm, size, fname, gpool);
-            }
+            apr_shm_remove(fname, gpool);
+            rv = apr_shm_create(&shm, size, fname, gpool);
         }
         else {
-            rv = apr_shm_create(&shm, size, NULL, pool);
+            rv = apr_shm_create(&shm, size, NULL, gpool);
         }
         ap_log_error(APLOG_MARK, rv == APR_SUCCESS ? APLOG_DEBUG : APLOG_ERR,
                      rv, ap_server_conf, APLOGNO(02611)
-                     "create: apr_shm_%s(%s) %s",
-                     fbased && is_child_process() ? "attach" : "create",
-                     fname, rv == APR_SUCCESS ? "succeeded" : "failed");
+                     "create: apr_shm_create(%s) %s",
+                     fname ? fname : "",
+                     rv == APR_SUCCESS ? "succeeded" : "failed");
         if (rv != APR_SUCCESS) {
             return rv;
         }
-
-        desc = (sharedslotdesc_t *)apr_shm_baseaddr_get(shm);
-        memset(desc, 0, size);
-        desc->size = item_size;
-        desc->num = item_num;
-        desc->type = type;
-
+        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);
         /*
          * 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(desc, pname, size, pool);
+            rv = restore_slotmem(ptr, pname, dsize, pool);
             if (rv == APR_SUCCESS) {
                 restored = 1;
             }
             else {
                 /* just in case, re-zero */
-                ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
+                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
                              APLOGNO(02554) "could not restore %s", fname);
-                memset((char *)desc + AP_SLOTMEM_OFFSET, 0,
-                       size - AP_SLOTMEM_OFFSET);
+                memset(ptr, 0, dsize);
             }
         }
     }
 
-    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, name);
-        res->pname = apr_pstrdup(p, pname);
-        *new = res;
-    }
-    res->fname = apr_pstrdup(p, fname);
+    /* 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);
     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->pool = pool;
+    res->gpool = gpool;
     res->next = NULL;
     res->inuse = ptr + basesize;
-    if (fbased) {
-        if (globallistmem == NULL) {
-            globallistmem = res;
-        }
-        else {
-            next->next = res;
-        }
+    if (globallistmem == NULL) {
+        globallistmem = res;
+    }
+    else {
+        next->next = res;
     }
 
+    *new = res;
     return APR_SUCCESS;
 }
 
@@ -580,33 +480,33 @@ static apr_status_t slotmem_attach(ap_slotmem_instance_t **new,
     char *ptr;
     ap_slotmem_instance_t *res;
     ap_slotmem_instance_t *next = globallistmem;
-    sharedslotdesc_t *desc;
-    int generation = 0;
+    sharedslotdesc_t desc;
     const char *fname;
     apr_shm_t *shm;
     apr_status_t rv;
 
-    ap_mpm_query(AP_MPMQ_GENERATION, &generation);
-
+    if (gpool == NULL) {
+        return APR_ENOSHMAVAIL;
+    }
     if (!slotmem_filenames(pool, name, &fname, NULL)) {
         return APR_ENOSHMAVAIL;
     }
 
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02301)
-                 "attach looking for %s", name);
+                 "attach looking for %s", fname);
 
     /* first try to attach to existing slotmem */
     if (next) {
         for (;;) {
-            if (strcmp(next->name, name) == 0) {
+            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",
-                             next->fname, *item_size, *item_num);
+                             "attach found %s: %"APR_SIZE_T_FMT"/%u", fname,
+                             *item_size, *item_num);
                 return APR_SUCCESS;
             }
             if (!next->next) {
@@ -617,37 +517,44 @@ static apr_status_t slotmem_attach(ap_slotmem_instance_t **new,
     }
 
     /* next try to attach to existing shared memory */
-    rv = slotmem_attach_shm(&shm, &fname, generation, pool);
+    rv = apr_shm_attach(&shm, fname, gpool);
     if (rv != APR_SUCCESS) {
         return rv;
     }
 
     /* Read the description of the slotmem */
-    desc = (sharedslotdesc_t *)apr_shm_baseaddr_get(shm);
-    ptr = (char *)desc + AP_SLOTMEM_OFFSET;
+    ptr = (char *)apr_shm_baseaddr_get(shm);
+    memcpy(&desc, ptr, sizeof(desc));
+    ptr += AP_SLOTMEM_OFFSET;
 
     /* For the chained slotmem stuff */
-    res = apr_pcalloc(pool, sizeof(ap_slotmem_instance_t));
-    res->name = apr_pstrdup(pool, name);
-    res->fname = apr_pstrdup(pool, fname);
+    res = (ap_slotmem_instance_t *) apr_pcalloc(gpool,
+                                                sizeof(ap_slotmem_instance_t));
+    res->name = apr_pstrdup(gpool, 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->pool = pool;
-    res->inuse = ptr + (desc->size * desc->num);
+    res->gpool = gpool;
+    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",
-                 res->fname, *item_size, *item_num);
+                 "attach found %s: %"APR_SIZE_T_FMT"/%u", fname,
+                 *item_size, *item_num);
     return APR_SUCCESS;
 }
 
@@ -659,11 +566,11 @@ static apr_status_t slotmem_dptr(ap_slotmem_instance_t *slot,
     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;
     }
@@ -683,7 +590,7 @@ static apr_status_t slotmem_get(ap_slotmem_instance_t *slot, unsigned int id,
     }
 
     inuse = slot->inuse + id;
-    if (id >= slot->desc->num) {
+    if (id >= slot->desc.num) {
         return APR_EINVAL;
     }
     if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) {
@@ -710,7 +617,7 @@ static apr_status_t slotmem_put(ap_slotmem_instance_t *slot, unsigned int id,
     }
 
     inuse = slot->inuse + id;
-    if (id >= slot->desc->num) {
+    if (id >= slot->desc.num) {
         return APR_EINVAL;
     }
     if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) {
@@ -727,7 +634,7 @@ static apr_status_t slotmem_put(ap_slotmem_instance_t *slot, unsigned int id,
 
 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)
@@ -737,7 +644,7 @@ static unsigned int slotmem_num_free_slots(ap_slotmem_instance_t *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++;
         }
@@ -747,7 +654,7 @@ static unsigned int slotmem_num_free_slots(ap_slotmem_instance_t *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)
@@ -761,12 +668,12 @@ static apr_status_t slotmem_grab(ap_slotmem_instance_t *slot, unsigned int *id)
 
     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),
@@ -787,7 +694,7 @@ static apr_status_t slotmem_fgrab(ap_slotmem_instance_t *slot, unsigned int id)
         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),
@@ -814,12 +721,12 @@ static apr_status_t slotmem_release(ap_slotmem_instance_t *slot,
 
     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;
@@ -852,41 +759,33 @@ static const ap_slotmem_provider_t *slotmem_shm_getstorage(void)
     return (&storage);
 }
 
-/* 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.
+/* initialise the global pool */
+static void slotmem_shm_initgpool(apr_pool_t *p)
+{
+    gpool = p;
+}
+
+/* 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
  */
-static int pre_config(apr_pool_t *pconf, apr_pool_t *plog,
-                      apr_pool_t *ptemp)
+static int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
+                       server_rec *s)
 {
-    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);
-    }
-
-    /* For the first (dry-)load, create SHMs on pconf and let them be
-     * cleaned up with it before the real loading. In any other case, SHMs
-     * shall have the same lifetime as the retained list (ap_pglobal), so
-     * the cleanup is to update the retained list on restart, and to unlink
-     * the SHMs on stop. This also works for MPM winnt child process which
-     * should rebuild the list first (i.e. attach SHMs, see slotmem_create),
-     * and try to cleanup/remove SHMs before exiting (see cleanup_slotmem).
-     */
-    if (ap_state_query(AP_SQ_MAIN_STATE) != AP_SQ_MS_CREATE_PRE_CONFIG) {
-        apr_pool_cleanup_register(pconf, NULL, cleanup_slotmem,
-                                  apr_pool_cleanup_null);
-        globallistmem = *retained_globallistmem;
-        gpool = ap_pglobal;
-    }
-    else {
-        globallistmem = NULL;
-        gpool = pconf;
-    }
+    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;
 }
 
@@ -895,6 +794,7 @@ 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);
 }