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 *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * http://www.apache.org/licenses/LICENSE-2.0
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
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 */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Memory handler for a shared memory divided in slot.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * This one uses shared memory.
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding */
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#include "ap_slotmem.h"
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#include "httpd.h"
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#ifdef AP_NEED_SET_MUTEX_PERMS
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "unixd.h"
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#endif
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#if APR_HAVE_UNISTD_H
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#include <unistd.h> /* for getpid() */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#if HAVE_SYS_SEM_H
64185f9824e42f21ca7b9ae6c004484215c031a7rbb#include <sys/shm.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#if !defined(SHM_R)
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#define SHM_R 0400
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#endif
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#if !defined(SHM_W)
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#define SHM_W 0200
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#endif
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffieldingstruct ap_slotmem_instance_t {
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding char *name; /* per segment name */
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding void *shm; /* ptr to memory segment (apr_shm_t *) */
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding void *base; /* data set start */
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding apr_size_t size; /* size of each memory slot */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding unsigned int num; /* number of mem slots */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_pool_t *gpool; /* per segment global pool */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_global_mutex_t *smutex; /* mutex */
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding struct ap_slotmem_instance_t *next; /* location of next allocated segment */
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding char *inuse; /* in-use flag table*/
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding};
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding/* The description of the slots to reuse the slotmem */
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffieldingstruct sharedslotdesc {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_size_t item_size;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding unsigned int item_num;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding};
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
785be1b6298010956622771c870ab3cd8ca57a2faaron/*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Memory layout:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * sharedslotdesc | slots | isuse array
1b21d7b3d97def358b2e923655edeb16613a1c31gstein */
1b21d7b3d97def358b2e923655edeb16613a1c31gstein
1b21d7b3d97def358b2e923655edeb16613a1c31gstein/* global pool and list of slotmem we are handling */
1b21d7b3d97def358b2e923655edeb16613a1c31gsteinstatic struct ap_slotmem_instance_t *globallistmem = NULL;
1b21d7b3d97def358b2e923655edeb16613a1c31gsteinstatic apr_pool_t *gpool = NULL;
1b21d7b3d97def358b2e923655edeb16613a1c31gsteinstatic apr_global_mutex_t *smutex = NULL;
1b21d7b3d97def358b2e923655edeb16613a1c31gsteinstatic const char *mutex_fname = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
2d71630471d1c23f0137309e3c3957c633ecbfd6rbb#define SLOTMEM_LOCK(s) do { \
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (s) \
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_global_mutex_lock(s); \
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding} while (0)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#define SLOTMEM_UNLOCK(s) do { \
51af95bb51b5084e883bad250b2afa2838e9ceebfielding if (s) \
d4f1d9c1ff112a8ab9bee31f196973761329b236rbb apr_global_mutex_unlock(s); \
7fae9cc4639013f3c04c085547256c68814aee8ftrawick} while (0)
7fae9cc4639013f3c04c085547256c68814aee8ftrawick
7fae9cc4639013f3c04c085547256c68814aee8ftrawick/* apr:shmem/unix/shm.c */
7fae9cc4639013f3c04c085547256c68814aee8ftrawickstatic apr_status_t unixd_set_shm_perms(const char *fname)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#ifdef AP_NEED_SET_MUTEX_PERMS
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding struct shmid_ds shmbuf;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding key_t shmkey;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int shmid;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding shmkey = ftok(fname, 1);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (shmkey == (key_t)-1) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return errno;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
785be1b6298010956622771c870ab3cd8ca57a2faaron if ((shmid = shmget(shmkey, 0, SHM_R | SHM_W)) == -1) {
785be1b6298010956622771c870ab3cd8ca57a2faaron return errno;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#if MODULE_MAGIC_NUMBER_MAJOR > 20081212
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding shmbuf.shm_perm.uid = ap_unixd_config.user_id;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding shmbuf.shm_perm.gid = ap_unixd_config.group_id;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#else
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding shmbuf.shm_perm.uid = unixd_config.user_id;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding shmbuf.shm_perm.gid = unixd_config.group_id;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding shmbuf.shm_perm.mode = 0600;
785be1b6298010956622771c870ab3cd8ca57a2faaron if (shmctl(shmid, IPC_SET, &shmbuf) == -1) {
785be1b6298010956622771c870ab3cd8ca57a2faaron return errno;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron return APR_SUCCESS;
785be1b6298010956622771c870ab3cd8ca57a2faaron#else
785be1b6298010956622771c870ab3cd8ca57a2faaron return APR_ENOTIMPL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#else
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm return APR_ENOTIMPL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Persiste the slotmem in a file
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * slotmem name and file name.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * anonymous : $server_root/logs/anonymous.slotmem
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * :module.c : $server_root/logs/module.c.slotmem
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * abs_name : $abs_name.slotmem
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *store_filename(apr_pool_t *pool, const char *slotmemname)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *storename;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *fname;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcmp(slotmemname, "anonymous") == 0)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding fname = ap_server_root_relative(pool, "logs/anonymous");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (slotmemname[0] == ':') {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *tmpname;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding tmpname = apr_pstrcat(pool, "logs/", &slotmemname[1], NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding fname = ap_server_root_relative(pool, tmpname);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding fname = slotmemname;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding storename = apr_pstrcat(pool, fname, ".slotmem", NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return storename;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void store_slotmem(ap_slotmem_instance_t *slotmem)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_file_t *fp;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_status_t rv;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_size_t nbytes;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *storename;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding storename = store_filename(slotmem->gpool, slotmem->name);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, slotmem->gpool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (APR_STATUS_IS_EEXIST(rv)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_file_remove(storename, slotmem->gpool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, slotmem->gpool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (rv != APR_SUCCESS) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding nbytes = (slotmem->size * slotmem->num) + (slotmem->num * sizeof(char));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_file_write(fp, slotmem->base, &nbytes);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_file_close(fp);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void restore_slotmem(void *ptr, const char *name, apr_size_t size, apr_pool_t *pool)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *storename;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_file_t *fp;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_size_t nbytes = size;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_status_t rv;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding storename = store_filename(pool, name);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rv = apr_file_open(&fp, storename, APR_READ | APR_WRITE, APR_OS_DEFAULT, pool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (rv == APR_SUCCESS) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_finfo_t fi;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (apr_file_info_get(&fi, APR_FINFO_SIZE, fp) == APR_SUCCESS) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (fi.size == nbytes) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_file_read(fp, ptr, &nbytes);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm }
785be1b6298010956622771c870ab3cd8ca57a2faaron else {
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick apr_file_close(fp);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_file_remove(storename, pool);
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick return;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick }
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick apr_file_close(fp);
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick }
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick}
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic apr_status_t cleanup_slotmem(void *param)
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick{
785be1b6298010956622771c870ab3cd8ca57a2faaron ap_slotmem_instance_t **mem = param;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_status_t rv;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick apr_pool_t *pool = NULL;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames if (*mem) {
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames ap_slotmem_instance_t *next = *mem;
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames pool = next->gpool;
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames while (next) {
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames store_slotmem(next);
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames rv = apr_shm_destroy((apr_shm_t *)next->shm);
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames next = next->next;
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames }
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames apr_pool_destroy(pool);
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames }
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick return APR_SUCCESS;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick}
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawickstatic apr_status_t slotmem_do(ap_slotmem_instance_t *mem, ap_slotmem_callback_fn_t *func, void *data, apr_pool_t *pool)
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick{
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick unsigned int i;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick void *ptr;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick char *inuse;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick if (!mem) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return APR_ENOSHMAVAIL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
eae32ab3fb398ca408bc2d45b22adf1b67a75471rbb
066877f1a045103acfdd376d48cdd473c33f409bdougm ptr = mem->base;
eae32ab3fb398ca408bc2d45b22adf1b67a75471rbb inuse = mem->inuse;
785be1b6298010956622771c870ab3cd8ca57a2faaron SLOTMEM_LOCK(mem->smutex);
785be1b6298010956622771c870ab3cd8ca57a2faaron for (i = 0; i < mem->num; i++, inuse++) {
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick if (*inuse) {
066877f1a045103acfdd376d48cdd473c33f409bdougm func((void *) ptr, data, pool);
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick }
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick ptr += mem->size;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron SLOTMEM_UNLOCK(mem->smutex);
066877f1a045103acfdd376d48cdd473c33f409bdougm return APR_SUCCESS;
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick}
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick
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{
74b39333600dee3260355ad3a06e36ef6c61c8f1dreid/* void *slotmem = NULL; */
74b39333600dee3260355ad3a06e36ef6c61c8f1dreid void *ptr;
74b39333600dee3260355ad3a06e36ef6c61c8f1dreid struct sharedslotdesc desc;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick ap_slotmem_instance_t *res;
066877f1a045103acfdd376d48cdd473c33f409bdougm ap_slotmem_instance_t *next = globallistmem;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick const char *fname;
d17890657bc529b3f9db20e5546511182b829565dreid apr_shm_t *shm;
d17890657bc529b3f9db20e5546511182b829565dreid apr_size_t basesize = (item_size * item_num);
d17890657bc529b3f9db20e5546511182b829565dreid apr_size_t size = sizeof(struct sharedslotdesc) + (item_num * sizeof(char)) + basesize;
d17890657bc529b3f9db20e5546511182b829565dreid apr_status_t rv;
d17890657bc529b3f9db20e5546511182b829565dreid
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick if (gpool == NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return APR_ENOSHMAVAIL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (name) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (name[0] == ':') {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding fname = name;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
785be1b6298010956622771c870ab3cd8ca57a2faaron else {
785be1b6298010956622771c870ab3cd8ca57a2faaron fname = ap_server_root_relative(pool, name);
785be1b6298010956622771c870ab3cd8ca57a2faaron }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* first try to attach to existing slotmem */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (next) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcmp(next->name, fname) == 0) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* we already have it */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *new = next;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return APR_SUCCESS;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron next = next->next;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding fname = "anonymous";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* first try to attach to existing shared memory */
785be1b6298010956622771c870ab3cd8ca57a2faaron if (name && name[0] != ':') {
785be1b6298010956622771c870ab3cd8ca57a2faaron rv = apr_shm_attach(&shm, fname, gpool);
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rv = APR_EINVAL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (rv == APR_SUCCESS) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* check size */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (apr_shm_size_get(shm) != size) {
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_shm_detach(shm);
785be1b6298010956622771c870ab3cd8ca57a2faaron return APR_EINVAL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ptr = apr_shm_baseaddr_get(shm);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding memcpy(&desc, ptr, sizeof(desc));
785be1b6298010956622771c870ab3cd8ca57a2faaron if (desc.item_size != item_size || desc.item_num != item_num) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_shm_detach(shm);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return APR_EINVAL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ptr = ptr + sizeof(desc);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_size_t dsize = size - sizeof(struct sharedslotdesc);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SLOTMEM_LOCK(smutex);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (name && name[0] != ':') {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_shm_remove(fname, gpool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rv = apr_shm_create(&shm, size, fname, gpool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rv = apr_shm_create(&shm, size, NULL, gpool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding SLOTMEM_UNLOCK(smutex);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (rv != APR_SUCCESS) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return rv;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (name && name[0] != ':') {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Set permissions to shared memory
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * so it can be attached by child process
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * having different user credentials
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
785be1b6298010956622771c870ab3cd8ca57a2faaron * See apr:shmem/unix/shm.c
785be1b6298010956622771c870ab3cd8ca57a2faaron */
785be1b6298010956622771c870ab3cd8ca57a2faaron unixd_set_shm_perms(fname);
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron ptr = apr_shm_baseaddr_get(shm);
785be1b6298010956622771c870ab3cd8ca57a2faaron desc.item_size = item_size;
785be1b6298010956622771c870ab3cd8ca57a2faaron desc.item_num = item_num;
785be1b6298010956622771c870ab3cd8ca57a2faaron memcpy(ptr, &desc, sizeof(desc));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ptr = ptr + sizeof(desc);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding memset(ptr, 0, dsize);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if (type & AP_SLOTMEM_TYPE_PERSIST)
785be1b6298010956622771c870ab3cd8ca57a2faaron restore_slotmem(ptr, fname, dsize, pool);
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* For the chained slotmem stuff */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding res = (ap_slotmem_instance_t *) apr_pcalloc(gpool, sizeof(ap_slotmem_instance_t));
785be1b6298010956622771c870ab3cd8ca57a2faaron res->name = apr_pstrdup(gpool, fname);
785be1b6298010956622771c870ab3cd8ca57a2faaron res->shm = shm;
785be1b6298010956622771c870ab3cd8ca57a2faaron res->base = ptr;
785be1b6298010956622771c870ab3cd8ca57a2faaron res->size = item_size;
785be1b6298010956622771c870ab3cd8ca57a2faaron res->num = item_num;
785be1b6298010956622771c870ab3cd8ca57a2faaron res->gpool = gpool;
785be1b6298010956622771c870ab3cd8ca57a2faaron res->smutex = smutex;
785be1b6298010956622771c870ab3cd8ca57a2faaron res->next = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding res->inuse = ptr + basesize;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if (globallistmem == NULL) {
785be1b6298010956622771c870ab3cd8ca57a2faaron globallistmem = res;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding next->next = res;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *new = res;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return APR_SUCCESS;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
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{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* void *slotmem = NULL; */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding void *ptr;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_slotmem_instance_t *res;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_slotmem_instance_t *next = globallistmem;
a7ed9c525f9460187f327cea953bf90ecf1bdc51gstein struct sharedslotdesc desc;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *fname;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_shm_t *shm;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_status_t rv;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (gpool == NULL) {
a7ed9c525f9460187f327cea953bf90ecf1bdc51gstein return APR_ENOSHMAVAIL;
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick }
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick if (name) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (name[0] == ':') {
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick fname = name;
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick }
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick else {
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick fname = ap_server_root_relative(pool, name);
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick }
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick }
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return APR_ENOSHMAVAIL;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm }
785be1b6298010956622771c870ab3cd8ca57a2faaron
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* first try to attach to existing slotmem */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (next) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcmp(next->name, fname) == 0) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* we already have it */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *new = next;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *item_size = next->size;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *item_num = next->num;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return APR_SUCCESS;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding next = next->next;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
785be1b6298010956622771c870ab3cd8ca57a2faaron /* first try to attach to existing shared memory */
785be1b6298010956622771c870ab3cd8ca57a2faaron rv = apr_shm_attach(&shm, fname, gpool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (rv != APR_SUCCESS) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return rv;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Read the description of the slotmem */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ptr = apr_shm_baseaddr_get(shm);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding memcpy(&desc, ptr, sizeof(desc));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ptr = ptr + sizeof(desc);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* For the chained slotmem stuff */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding res = (ap_slotmem_instance_t *) apr_pcalloc(gpool, sizeof(ap_slotmem_instance_t));
a7ed9c525f9460187f327cea953bf90ecf1bdc51gstein res->name = apr_pstrdup(gpool, fname);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding res->shm = shm;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding res->base = ptr;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding res->size = desc.item_size;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding res->num = desc.item_num;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm res->gpool = gpool;
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick res->smutex = smutex;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding res->inuse = ptr + (desc.item_size * desc.item_num);
785be1b6298010956622771c870ab3cd8ca57a2faaron res->next = NULL;
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick if (globallistmem == NULL) {
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick globallistmem = res;
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick }
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick else {
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick next->next = res;
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick }
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick *new = res;
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick *item_size = desc.item_size;
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick *item_num = desc.item_num;
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick return APR_SUCCESS;
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic apr_status_t slotmem_mem(ap_slotmem_instance_t *slot, unsigned int id, void **mem)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding void *ptr;
8f8ec0957334f50b7ac11359f90490ee467258eedreid
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (!slot) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return APR_ENOSHMAVAIL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (id < 0 || id >= slot->num) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return APR_ENOSHMAVAIL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ptr = slot->base + slot->size * id;
785be1b6298010956622771c870ab3cd8ca57a2faaron if (!ptr) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return APR_ENOSHMAVAIL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *mem = ptr;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return APR_SUCCESS;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic apr_status_t slotmem_get(ap_slotmem_instance_t *slot, unsigned int id, unsigned char *dest, apr_size_t dest_len)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding void *ptr;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick char *inuse;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_status_t ret;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick if (!slot) {
785be1b6298010956622771c870ab3cd8ca57a2faaron return APR_ENOSHMAVAIL;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick inuse = slot->inuse;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick if (id >= slot->num || !inuse[id] ) {
785be1b6298010956622771c870ab3cd8ca57a2faaron return APR_NOTFOUND;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf ret = slotmem_mem(slot, id, &ptr);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf if (ret != APR_SUCCESS) {
785be1b6298010956622771c870ab3cd8ca57a2faaron return ret;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf }
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf memcpy(dest, ptr, dest_len); /* bounds check? */
785be1b6298010956622771c870ab3cd8ca57a2faaron return APR_SUCCESS;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf}
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic apr_status_t slotmem_put(ap_slotmem_instance_t *slot, unsigned int id, unsigned char *src, apr_size_t src_len)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron void *ptr;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf char *inuse;
066877f1a045103acfdd376d48cdd473c33f409bdougm apr_status_t ret;
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron if (!slot) {
785be1b6298010956622771c870ab3cd8ca57a2faaron return APR_ENOSHMAVAIL;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf }
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron inuse = slot->inuse;
785be1b6298010956622771c870ab3cd8ca57a2faaron if (id >= slot->num || !inuse[id] ) {
785be1b6298010956622771c870ab3cd8ca57a2faaron return APR_NOTFOUND;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron ret = slotmem_mem(slot, id, &ptr);
785be1b6298010956622771c870ab3cd8ca57a2faaron if (ret != APR_SUCCESS) {
785be1b6298010956622771c870ab3cd8ca57a2faaron return ret;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf memcpy(ptr, src, src_len); /* bounds check? */
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf return APR_SUCCESS;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf}
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanfstatic unsigned int slotmem_num_slots(ap_slotmem_instance_t *slot)
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf{
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf return slot->num;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf}
066877f1a045103acfdd376d48cdd473c33f409bdougm
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic apr_size_t slotmem_slot_size(ap_slotmem_instance_t *slot)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
785be1b6298010956622771c870ab3cd8ca57a2faaron return slot->size;
785be1b6298010956622771c870ab3cd8ca57a2faaron}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic apr_status_t slotmem_grab(ap_slotmem_instance_t *slot, unsigned int *id)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron unsigned int i;
785be1b6298010956622771c870ab3cd8ca57a2faaron char *inuse;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf if (!slot) {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf return APR_ENOSHMAVAIL;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf }
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf inuse = slot->inuse;
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron SLOTMEM_LOCK(slot->smutex);
785be1b6298010956622771c870ab3cd8ca57a2faaron for (i = 0; i < slot->num; i++, inuse++) {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf if (!*inuse) {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf break;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf }
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf }
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf if (i >= slot->num) {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf SLOTMEM_UNLOCK(slot->smutex);
785be1b6298010956622771c870ab3cd8ca57a2faaron return APR_ENOSHMAVAIL;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron *inuse = 1;
785be1b6298010956622771c870ab3cd8ca57a2faaron *id = i;
785be1b6298010956622771c870ab3cd8ca57a2faaron SLOTMEM_UNLOCK(slot->smutex);
785be1b6298010956622771c870ab3cd8ca57a2faaron return APR_SUCCESS;
785be1b6298010956622771c870ab3cd8ca57a2faaron}
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic apr_status_t slotmem_return(ap_slotmem_instance_t *slot, unsigned int id)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron char *inuse;
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron if (!slot) {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf return APR_ENOSHMAVAIL;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf }
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron inuse = slot->inuse;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf SLOTMEM_LOCK(slot->smutex);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf if (id >= slot->num || !inuse[id] ) {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf SLOTMEM_UNLOCK(slot->smutex);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf return APR_NOTFOUND;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf }
785be1b6298010956622771c870ab3cd8ca57a2faaron inuse[id] = 0;
785be1b6298010956622771c870ab3cd8ca57a2faaron SLOTMEM_UNLOCK(slot->smutex);
785be1b6298010956622771c870ab3cd8ca57a2faaron return APR_SUCCESS;
785be1b6298010956622771c870ab3cd8ca57a2faaron}
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic const ap_slotmem_provider_t storage = {
785be1b6298010956622771c870ab3cd8ca57a2faaron "sharedmem",
785be1b6298010956622771c870ab3cd8ca57a2faaron &slotmem_do,
785be1b6298010956622771c870ab3cd8ca57a2faaron &slotmem_create,
785be1b6298010956622771c870ab3cd8ca57a2faaron &slotmem_attach,
785be1b6298010956622771c870ab3cd8ca57a2faaron &slotmem_mem,
785be1b6298010956622771c870ab3cd8ca57a2faaron &slotmem_get,
785be1b6298010956622771c870ab3cd8ca57a2faaron &slotmem_put,
785be1b6298010956622771c870ab3cd8ca57a2faaron &slotmem_num_slots,
785be1b6298010956622771c870ab3cd8ca57a2faaron &slotmem_slot_size
785be1b6298010956622771c870ab3cd8ca57a2faaron};
785be1b6298010956622771c870ab3cd8ca57a2faaron
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* make the storage usuable from outside */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const ap_slotmem_provider_t *slotmem_shm_getstorage(void)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return (&storage);
ebc18d48bea83ee5ed7a1b4e30007e5192539829wrowe}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* initialise the global pool */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void slotmem_shm_initgpool(apr_pool_t *p)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding gpool = p;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Add the pool_clean routine */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void slotmem_shm_initialize_cleanup(apr_pool_t *p)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_pool_cleanup_register(p, &globallistmem, cleanup_slotmem, apr_pool_cleanup_null);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*
785be1b6298010956622771c870ab3cd8ca57a2faaron * Create the shared mem mutex and
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * make sure the shared memory is cleaned
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
785be1b6298010956622771c870ab3cd8ca57a2faaron const char *temp_dir;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *template;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_status_t rv;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm void *data;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_file_t *fmutex;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *userdata_key = "slotmem_shm_post_config";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_pool_userdata_get(&data, userdata_key, s->process->pool);
785be1b6298010956622771c870ab3cd8ca57a2faaron if (!data) {
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_pool_userdata_set((const void *)1, userdata_key,
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_pool_cleanup_null, s->process->pool);
785be1b6298010956622771c870ab3cd8ca57a2faaron return OK;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron rv = apr_temp_dir_get(&temp_dir, p);
785be1b6298010956622771c870ab3cd8ca57a2faaron if (rv != APR_SUCCESS) {
785be1b6298010956622771c870ab3cd8ca57a2faaron ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
785be1b6298010956622771c870ab3cd8ca57a2faaron "slotmem_shm: search for temporary directory failed");
785be1b6298010956622771c870ab3cd8ca57a2faaron return rv;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_filepath_merge(&template, temp_dir, "slotmem_shm.lck.XXXXXX",
785be1b6298010956622771c870ab3cd8ca57a2faaron APR_FILEPATH_NATIVE, p);
785be1b6298010956622771c870ab3cd8ca57a2faaron rv = apr_file_mktemp(&fmutex, template, 0, p);
785be1b6298010956622771c870ab3cd8ca57a2faaron if (rv != APR_SUCCESS) {
785be1b6298010956622771c870ab3cd8ca57a2faaron ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
785be1b6298010956622771c870ab3cd8ca57a2faaron "slotmem_shm: creation of mutex file in directory %s failed",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding temp_dir);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return rv;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rv = apr_file_name_get(&mutex_fname, fmutex);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (rv != APR_SUCCESS) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "slotmem_shm: unable to get mutex fname");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return rv;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron rv = apr_file_close(fmutex);
785be1b6298010956622771c870ab3cd8ca57a2faaron if (rv != APR_SUCCESS) {
785be1b6298010956622771c870ab3cd8ca57a2faaron ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
785be1b6298010956622771c870ab3cd8ca57a2faaron "slotmem_shm: could not close mutex file");
785be1b6298010956622771c870ab3cd8ca57a2faaron return rv;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron rv = apr_global_mutex_create(&smutex,
785be1b6298010956622771c870ab3cd8ca57a2faaron mutex_fname, APR_LOCK_DEFAULT, p);
785be1b6298010956622771c870ab3cd8ca57a2faaron if (rv != APR_SUCCESS) {
785be1b6298010956622771c870ab3cd8ca57a2faaron ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
785be1b6298010956622771c870ab3cd8ca57a2faaron "slotmem_shm: creation of mutex failed");
785be1b6298010956622771c870ab3cd8ca57a2faaron return rv;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron#ifdef AP_NEED_SET_MUTEX_PERMS
785be1b6298010956622771c870ab3cd8ca57a2faaron rv = ap_unixd_set_global_mutex_perms(smutex);
785be1b6298010956622771c870ab3cd8ca57a2faaron if (rv != APR_SUCCESS) {
785be1b6298010956622771c870ab3cd8ca57a2faaron ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
785be1b6298010956622771c870ab3cd8ca57a2faaron "slotmem_shm: failed to set mutex permissions");
785be1b6298010956622771c870ab3cd8ca57a2faaron return rv;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron#endif
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron slotmem_shm_initialize_cleanup(p);
785be1b6298010956622771c870ab3cd8ca57a2faaron return OK;
785be1b6298010956622771c870ab3cd8ca57a2faaron}
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic int pre_config(apr_pool_t *p, apr_pool_t *plog,
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_pool_t *ptemp)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_pool_t *global_pool;
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_status_t rv;
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron rv = apr_pool_create(&global_pool, NULL);
785be1b6298010956622771c870ab3cd8ca57a2faaron if (rv != APR_SUCCESS) {
785be1b6298010956622771c870ab3cd8ca57a2faaron ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
785be1b6298010956622771c870ab3cd8ca57a2faaron "Fatal error: unable to create global pool for shared slotmem");
785be1b6298010956622771c870ab3cd8ca57a2faaron return rv;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron slotmem_shm_initgpool(global_pool);
785be1b6298010956622771c870ab3cd8ca57a2faaron return OK;
785be1b6298010956622771c870ab3cd8ca57a2faaron}
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic void child_init(apr_pool_t *p, server_rec *s)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_status_t rv;
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron rv = apr_global_mutex_child_init(&smutex,
785be1b6298010956622771c870ab3cd8ca57a2faaron mutex_fname, p);
785be1b6298010956622771c870ab3cd8ca57a2faaron if (rv != APR_SUCCESS) {
785be1b6298010956622771c870ab3cd8ca57a2faaron ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
785be1b6298010956622771c870ab3cd8ca57a2faaron "Failed to initialise global mutex %s in child process %"
785be1b6298010956622771c870ab3cd8ca57a2faaron APR_PID_T_FMT ".",
785be1b6298010956622771c870ab3cd8ca57a2faaron mutex_fname, getpid());
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron}
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic void ap_slotmem_shm_register_hook(apr_pool_t *p)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
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);
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick ap_hook_child_init(child_init, NULL, NULL, APR_HOOK_MIDDLE);
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick}
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronmodule AP_MODULE_DECLARE_DATA slotmem_shm_module = {
785be1b6298010956622771c870ab3cd8ca57a2faaron STANDARD20_MODULE_STUFF,
785be1b6298010956622771c870ab3cd8ca57a2faaron NULL, /* create per-directory config structure */
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick NULL, /* merge per-directory config structures */
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick NULL, /* create per-server config structure */
066877f1a045103acfdd376d48cdd473c33f409bdougm NULL, /* merge per-server config structures */
785be1b6298010956622771c870ab3cd8ca57a2faaron NULL, /* command apr_table_t */
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick ap_slotmem_shm_register_hook /* register hooks */
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick};
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick