Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions Utilities/Adaptors/Adaptor/shmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,33 @@ int WOShmem_init(const char *file, size_t memsize)
return WOShmem_fd == -1;
}

/*
* Release the mapping made by WOShmem_init() and close its file descriptor.
*
* Apache unloads and reloads this module on every graceful restart or restart
* (SIGUSR1 / SIGHUP), which resets the statics above and runs WOShmem_init()
* again in the SAME parent process: a fresh, already-unlinked state file was
* mapped each time and the previous mapping was never released. On a 32-bit
* server every restart therefore ate address space until mmap() failed with
* ENOMEM ("WOShmem_init(): couldn't map file: Not enough space") and the
* adaptor declined every request until Apache was fully stopped and started
* (seen 2026-09-27 on an AIX box after about a year of nightly logrotate
* restarts). The Apache module calls this from a cleanup registered on the
* configuration pool, which Apache clears before each restart.
* Safe to call when nothing is mapped. Children that still hold the old
* mapping are not affected: the file lives on until its last mapping goes.
*/
void WOShmem_cleanup(void)
{
if (WOShmem_base_address != MAP_FAILED && WOShmem_size != 0 && WOShmem_size != (unsigned int)-1)
munmap(WOShmem_base_address, WOShmem_size);
WOShmem_base_address = MAP_FAILED;
WOShmem_size = 0;
if (WOShmem_fd != -1)
close(WOShmem_fd);
WOShmem_fd = -1;
}



void *WOShmem_alloc(const char *regionName, size_t elementSize, unsigned int *elementCount)
Expand Down
5 changes: 5 additions & 0 deletions Utilities/Adaptors/Adaptor/shmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ and limitations under the License.
*/
int WOShmem_init(const char *file, size_t memsize);

/*
* Unmap the shared memory and close the backing file. See shmem.c.
*/
void WOShmem_cleanup(void);

/*
* Allocate or look up a chunk of shared memory.
* regionName specifies the name of the region to locate.
Expand Down
24 changes: 24 additions & 0 deletions Utilities/Adaptors/Apache2.4/mod_WebObjects.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
*/

#include "config.h"
#include "shmem.h"
#include "womalloc.h"
#include "request.h"
#include "response.h"
Expand Down Expand Up @@ -617,10 +618,31 @@ static void *WebObjects_create_config(apr_pool_t *p, server_rec *s)
* to assume it's in the apache conf directory.
*
*/
/*
* Runs when Apache clears the configuration pool: at every graceful restart or
* restart, before the configuration is read again and this module is reloaded.
* Releases the shared-memory mapping that init_adaptor() made (see
* WOShmem_cleanup in shmem.c for why this matters).
*/
static apr_status_t WebObjects_shutdown(void *data) {
WOShmem_cleanup();
adaptorEnabled = 0;
initCalled = 0;
return APR_SUCCESS;
}

static int WebObjects_post_config(apr_pool_t *pconf, apr_pool_t *plog,
apr_pool_t *ptemp, server_rec *s) {
WebObjects_config *wc;

/*
* Apache runs post_config twice when it starts (the first pass only checks
* the configuration) and once per restart. Nothing is mapped during the
* check pass, which also covers "apachectl configtest".
*/
if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG)
return OK;

if(!initCalled) {
_webobjects_server = s;
wc = (WebObjects_config *)ap_get_module_config(s->module_config, &WebObjects_module);
Expand All @@ -635,10 +657,12 @@ static int WebObjects_post_config(apr_pool_t *pconf, apr_pool_t *plog,
adaptorEnabled = 1;
} else {
WOLog(WO_ERR, "WebObjects_post_config(): Adaptor initialization failed. All requests will be declined.");
WOShmem_cleanup();
return DECLINED;
}

initCalled = 1;
apr_pool_cleanup_register(pconf, NULL, WebObjects_shutdown, apr_pool_cleanup_null);
}

return OK;
Expand Down
Loading