mod_slotmem_shm.c revision 84cf97736f2479e2924f62bf0b16cf50deeaae1d
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * contributor license agreements. See the NOTICE file distributed with
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * this work for additional information regarding copyright ownership.
b99dbaab171d91e1b664397cc40e039d0c087c65fielding * The ASF licenses this file to You under the Apache License, Version 2.0
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * (the "License"); you may not use this file except in compliance with
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the License. You may obtain a copy of the License at
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Unless required by applicable law or agreed to in writing, software
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * distributed under the License is distributed on an "AS IS" BASIS,
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * See the License for the specific language governing permissions and
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * limitations under the License.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Memory handler for a shared memory divided in slot.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * This one uses shared memory.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#if !defined(SHM_R)
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#if !defined(SHM_W)
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding void *shm; /* ptr to memory segment (apr_shm_t *) */
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding struct ap_slotmem_instance_t *next; /* location of next allocated segment */
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding/* The description of the slots to reuse the slotmem */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding unsigned int item_num;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Memory layout:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * sharedslotdesc | slots | isuse array
1b21d7b3d97def358b2e923655edeb16613a1c31gstein/* global pool and list of slotmem we are handling */
1b21d7b3d97def358b2e923655edeb16613a1c31gsteinstatic struct ap_slotmem_instance_t *globallistmem = NULL;
2d71630471d1c23f0137309e3c3957c633ecbfd6rbb#define SLOTMEM_LOCK(s) do { \
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#define SLOTMEM_UNLOCK(s) do { \
7fae9cc4639013f3c04c085547256c68814aee8ftrawickstatic apr_status_t unixd_set_shm_perms(const char *fname)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON
785be1b6298010956622771c870ab3cd8ca57a2faaron if ((shmid = shmget(shmkey, 0, SHM_R | SHM_W)) == -1) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Persiste the slotmem in a file
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * slotmem name and file name.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * abs_name : $abs_name.slotmem
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *store_filename(apr_pool_t *pool, const char *slotmemname)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *fname;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding fname = ap_server_root_relative(pool, "logs/anonymous");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *tmpname;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding tmpname = apr_pstrcat(pool, "logs/", &slotmemname[1], NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding storename = apr_pstrcat(pool, fname, ".slotmem", NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void store_slotmem(ap_slotmem_instance_t *slotmem)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding storename = store_filename(slotmem->gpool, slotmem->name);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, slotmem->gpool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, slotmem->gpool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding nbytes = (slotmem->size * slotmem->num) + (slotmem->num * sizeof(char));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void restore_slotmem(void *ptr, const char *name, apr_size_t size, apr_pool_t *pool)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rv = apr_file_open(&fp, storename, APR_READ | APR_WRITE, APR_OS_DEFAULT, pool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (apr_file_info_get(&fi, APR_FINFO_SIZE, fp) == APR_SUCCESS) {
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawickstatic apr_status_t slotmem_do(ap_slotmem_instance_t *mem, ap_slotmem_callback_fn_t *func, void *data, apr_pool_t *pool)
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick unsigned int i;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawickstatic apr_status_t slotmem_create(ap_slotmem_instance_t **new, const char *name, apr_size_t item_size, unsigned int item_num, ap_slotmem_type_t type, apr_pool_t *pool)
74b39333600dee3260355ad3a06e36ef6c61c8f1dreid/* void *slotmem = NULL; */
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick const char *fname;
d17890657bc529b3f9db20e5546511182b829565dreid apr_size_t size = sizeof(struct sharedslotdesc) + (item_num * sizeof(char)) + basesize;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* first try to attach to existing slotmem */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* we already have it */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* first try to attach to existing shared memory */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* check size */
785be1b6298010956622771c870ab3cd8ca57a2faaron if (desc.item_size != item_size || desc.item_num != item_num) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_size_t dsize = size - sizeof(struct sharedslotdesc);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Set permissions to shared memory
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * so it can be attached by child process
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * having different user credentials
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* For the chained slotmem stuff */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding res = (ap_slotmem_instance_t *) apr_pcalloc(gpool, sizeof(ap_slotmem_instance_t));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic apr_status_t slotmem_attach(ap_slotmem_instance_t **new, const char *name, apr_size_t *item_size, unsigned int *item_num, apr_pool_t *pool)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* void *slotmem = NULL; */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *fname;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* first try to attach to existing slotmem */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* we already have it */
785be1b6298010956622771c870ab3cd8ca57a2faaron /* first try to attach to existing shared memory */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Read the description of the slotmem */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* For the chained slotmem stuff */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding res = (ap_slotmem_instance_t *) apr_pcalloc(gpool, sizeof(ap_slotmem_instance_t));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding res->inuse = ptr + (desc.item_size * desc.item_num);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic apr_status_t slotmem_mem(ap_slotmem_instance_t *slot, unsigned int id, void **mem)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic apr_status_t slotmem_get(ap_slotmem_instance_t *slot, unsigned int id, unsigned char *dest, apr_size_t dest_len)
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic apr_status_t slotmem_put(ap_slotmem_instance_t *slot, unsigned int id, unsigned char *src, apr_size_t src_len)
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanfstatic unsigned int slotmem_num_slots(ap_slotmem_instance_t *slot)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic apr_size_t slotmem_slot_size(ap_slotmem_instance_t *slot)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic apr_status_t slotmem_grab(ap_slotmem_instance_t *slot, unsigned int *id)
785be1b6298010956622771c870ab3cd8ca57a2faaron unsigned int i;
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic apr_status_t slotmem_return(ap_slotmem_instance_t *slot, unsigned int id)
785be1b6298010956622771c870ab3cd8ca57a2faaron "sharedmem",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* make the storage usuable from outside */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const ap_slotmem_provider_t *slotmem_shm_getstorage(void)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* initialise the global pool */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Add the pool_clean routine */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void slotmem_shm_initialize_cleanup(apr_pool_t *p)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_pool_cleanup_register(p, &globallistmem, cleanup_slotmem, apr_pool_cleanup_null);
785be1b6298010956622771c870ab3cd8ca57a2faaron * Create the shared mem mutex and
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * make sure the shared memory is cleaned
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
785be1b6298010956622771c870ab3cd8ca57a2faaron const char *temp_dir;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *userdata_key = "slotmem_shm_post_config";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_pool_userdata_get(&data, userdata_key, s->process->pool);
785be1b6298010956622771c870ab3cd8ca57a2faaron "slotmem_shm: search for temporary directory failed");
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_filepath_merge(&template, temp_dir, "slotmem_shm.lck.XXXXXX",
785be1b6298010956622771c870ab3cd8ca57a2faaron "slotmem_shm: creation of mutex file in directory %s failed",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "slotmem_shm: unable to get mutex fname");
785be1b6298010956622771c870ab3cd8ca57a2faaron "slotmem_shm: could not close mutex file");
785be1b6298010956622771c870ab3cd8ca57a2faaron "slotmem_shm: creation of mutex failed");
785be1b6298010956622771c870ab3cd8ca57a2faaron "slotmem_shm: failed to set mutex permissions");
785be1b6298010956622771c870ab3cd8ca57a2faaron "Fatal error: unable to create global pool for shared slotmem");
785be1b6298010956622771c870ab3cd8ca57a2faaron "Failed to initialise global mutex %s in child process %"
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic void ap_slotmem_shm_register_hook(apr_pool_t *p)
785be1b6298010956622771c870ab3cd8ca57a2faaron const ap_slotmem_provider_t *storage = slotmem_shm_getstorage();
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick ap_register_provider(p, AP_SLOTMEM_PROVIDER_GROUP, "shared", "0", storage);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_hook_post_config(post_config, NULL, NULL, APR_HOOK_LAST);
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick ap_hook_pre_config(pre_config, NULL, NULL, APR_HOOK_MIDDLE);