View | Details | Raw Unified | Return to bug 62044
Collapse All | Expand All

(-)modules/proxy/mod_proxy_balancer.c (-10 / +117 lines)
Lines 22-27 Link Here
22
#include "apr_version.h"
22
#include "apr_version.h"
23
#include "ap_hooks.h"
23
#include "ap_hooks.h"
24
#include "apr_date.h"
24
#include "apr_date.h"
25
#include "apr_escape.h"
25
#include "mod_watchdog.h"
26
#include "mod_watchdog.h"
26
27
27
static const char *balancer_mutex_type = "proxy-balancer-shm";
28
static const char *balancer_mutex_type = "proxy-balancer-shm";
Lines 730-735 static apr_status_t lock_remove(void *data) Link Here
730
    return(0);
731
    return(0);
731
}
732
}
732
733
734
/*
735
 * Compute an ID for a vhost based on what makes it selected by requests.
736
 * The second and more Host(s)/IP(s):port(s), and the ServerAlias(es) are
737
 * optional (see make_servers_ids() below).
738
 */
739
 static const char *make_server_id(server_rec *s, apr_pool_t *p, int full)
740
{
741
    apr_md5_ctx_t md5_ctx;
742
    unsigned char md5[APR_MD5_DIGESTSIZE];
743
    char host_ip[64]; /* for any IPv[46] string */
744
    server_addr_rec *sar;
745
    int i;
746
747
    apr_md5_init(&md5_ctx);
748
    for (sar = s->addrs; sar; sar = sar->next) {
749
        host_ip[0] = '\0';
750
        apr_sockaddr_ip_getbuf(host_ip, sizeof host_ip, sar->host_addr);
751
        apr_md5_update(&md5_ctx, (void *)sar->virthost, strlen(sar->virthost));
752
        apr_md5_update(&md5_ctx, (void *)host_ip, strlen(host_ip));
753
        apr_md5_update(&md5_ctx, (void *)&sar->host_port,
754
                       sizeof(sar->host_port));
755
        if (!full) {
756
            break;
757
        }
758
    }
759
    if (s->server_hostname) {
760
        apr_md5_update(&md5_ctx, (void *)s->server_hostname,
761
                       strlen(s->server_hostname));
762
    }
763
    if (full) {
764
        if (s->names) {
765
            for (i = 0; i < s->names->nelts; ++i) {
766
                const char *name = APR_ARRAY_IDX(s->names, i, char *);
767
                apr_md5_update(&md5_ctx, (void *)name, strlen(name));
768
            }
769
        }
770
        if (s->wild_names) {
771
            for (i = 0; i < s->wild_names->nelts; ++i) {
772
                const char *name = APR_ARRAY_IDX(s->wild_names, i, char *);
773
                apr_md5_update(&md5_ctx, (void *)name, strlen(name));
774
            }
775
        }
776
    }
777
    apr_md5_final(md5, &md5_ctx);
778
779
    return apr_pescape_hex(p, md5, sizeof md5, 0);
780
}
781
782
/*
783
 * First try to compute an unique ID for each vhost with minimal criteria,
784
 * that is the first Host/IP:port and ServerName. For most cases this should
785
 * be enough and avoids changing the ID unnecessarily accross restart (or
786
 * stop/start w.r.t. persisted files) for things that this module does not
787
 * care about.
788
 *
789
 * But if it's not enough (collisions) do a second pass for the full monty,
790
 * that is additionally the other Host(s)/IP(s):port(s) and ServerAlias(es).
791
 *
792
 * Finally, for pathological configs where this is still not enough, let's
793
 * append a counter to duplicates, because we really want that ID to be unique
794
 * even if the vhost will never be selected to handle requests at run time, at
795
 * load time a duplicate may steal the original slotmems (depending on its
796
 * balancers' configurations), see how mod_slotmem_shm reuses slots/files based
797
 * solely on this ID and resets them if the sizes don't match.
798
 */
799
static apr_array_header_t *make_servers_ids(server_rec *main_s, apr_pool_t *p)
800
{
801
    server_rec *s = main_s;
802
    apr_array_header_t *ids = apr_array_make(p, 10, sizeof(const char *));
803
    apr_hash_t *dups = apr_hash_make(p);
804
    int idx, *dup, full_monty = 0;
805
    const char *id;
806
807
    for (idx = 0, s = main_s; s; s = s->next, ++idx) {
808
        id = make_server_id(s, p, 0);
809
        dup = apr_hash_get(dups, id, APR_HASH_KEY_STRING);
810
        apr_hash_set(dups, id, APR_HASH_KEY_STRING,
811
                     apr_pmemdup(p, &idx, sizeof(int)));
812
        if (dup) {
813
            full_monty = 1;
814
            APR_ARRAY_IDX(ids, *dup, const char *) = NULL;
815
            APR_ARRAY_PUSH(ids, const char *) = NULL;
816
        }
817
        else {
818
            APR_ARRAY_PUSH(ids, const char *) = id;
819
        }
820
    }
821
    if (full_monty) {
822
        apr_hash_clear(dups);
823
        for (idx = 0, s = main_s; s; s = s->next, ++idx) {
824
            id = APR_ARRAY_IDX(ids, idx, const char *);
825
            if (id) {
826
                /* Preserve non-duplicates */
827
                continue;
828
            }
829
            id = make_server_id(s, p, 1);
830
            if (apr_hash_get(dups, id, APR_HASH_KEY_STRING)) {
831
                id = apr_psprintf(p, "%s_%x", id, idx);
832
            }
833
            else {
834
                apr_hash_set(dups, id, APR_HASH_KEY_STRING, (void *)-1);
835
            }
836
            APR_ARRAY_IDX(ids, idx, const char *) = id;
837
        }
838
    }
839
840
    return ids;
841
}
842
733
/* post_config hook: */
843
/* post_config hook: */
734
static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog,
844
static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog,
735
                         apr_pool_t *ptemp, server_rec *s)
845
                         apr_pool_t *ptemp, server_rec *s)
Lines 738-743 static int balancer_post_config(apr_pool_t *pconf, Link Here
738
    proxy_server_conf *conf;
848
    proxy_server_conf *conf;
739
    ap_slotmem_instance_t *new = NULL;
849
    ap_slotmem_instance_t *new = NULL;
740
    apr_time_t tstamp;
850
    apr_time_t tstamp;
851
    apr_array_header_t *ids;
852
    int idx;
741
853
742
    /* balancer_post_config() will be called twice during startup.  So, don't
854
    /* balancer_post_config() will be called twice during startup.  So, don't
743
     * set up the static data the 1st time through. */
855
     * set up the static data the 1st time through. */
Lines 768-781 static int balancer_post_config(apr_pool_t *pconf, Link Here
768
        return !OK;
880
        return !OK;
769
    }
881
    }
770
882
883
    ids = make_servers_ids(s, ptemp);
884
771
    tstamp = apr_time_now();
885
    tstamp = apr_time_now();
772
    /*
886
    /*
773
     * Go thru each Vhost and create the shared mem slotmem for
887
     * Go thru each Vhost and create the shared mem slotmem for
774
     * each balancer's workers
888
     * each balancer's workers
775
     */
889
     */
776
    while (s) {
890
    for (idx = 0; s; ++idx) {
777
        int i,j;
891
        int i,j;
778
        char *id;
892
        const char *id;
779
        proxy_balancer *balancer;
893
        proxy_balancer *balancer;
780
        ap_slotmem_type_t type;
894
        ap_slotmem_type_t type;
781
        void *sconf = s->module_config;
895
        void *sconf = s->module_config;
Lines 784-797 static int balancer_post_config(apr_pool_t *pconf, Link Here
784
         * During create_proxy_config() we created a dummy id. Now that
898
         * During create_proxy_config() we created a dummy id. Now that
785
         * we have identifying info, we can create the real id
899
         * we have identifying info, we can create the real id
786
         */
900
         */
787
        id = apr_psprintf(pconf, "%s.%s.%d.%s.%s.%u.%s",
901
        id = APR_ARRAY_IDX(ids, idx, const char *);
788
                          (s->server_scheme ? s->server_scheme : "????"),
789
                          (s->server_hostname ? s->server_hostname : "???"),
790
                          (int)s->port,
791
                          (s->server_admin ? s->server_admin : "??"),
792
                          (s->defn_name ? s->defn_name : "?"),
793
                          s->defn_line_number,
794
                          (s->error_fname ? s->error_fname : DEFAULT_ERRORLOG));
795
        conf->id = apr_psprintf(pconf, "p%x",
902
        conf->id = apr_psprintf(pconf, "p%x",
796
                                ap_proxy_hashfunc(id, PROXY_HASHFUNC_DEFAULT));
903
                                ap_proxy_hashfunc(id, PROXY_HASHFUNC_DEFAULT));
797
        if (conf->bslot) {
904
        if (conf->bslot) {
(-)modules/slotmem/mod_slotmem_shm.c (-221 / +256 lines)
Lines 25-35 Link Here
25
25
26
#include "httpd.h"
26
#include "httpd.h"
27
#include "http_main.h"
27
#include "http_main.h"
28
#include "ap_mpm.h" /* for ap_mpm_query() */
28
#include "http_core.h"
29
29
30
#define AP_SLOTMEM_IS_PREGRAB(t)    (t->desc.type & AP_SLOTMEM_TYPE_PREGRAB)
30
#define AP_SLOTMEM_IS_PREGRAB(t)    (t->desc->type & AP_SLOTMEM_TYPE_PREGRAB)
31
#define AP_SLOTMEM_IS_PERSIST(t)    (t->desc.type & AP_SLOTMEM_TYPE_PERSIST)
31
#define AP_SLOTMEM_IS_PERSIST(t)    (t->desc->type & AP_SLOTMEM_TYPE_PERSIST)
32
#define AP_SLOTMEM_IS_CLEARINUSE(t) (t->desc.type & AP_SLOTMEM_TYPE_CLEARINUSE)
32
#define AP_SLOTMEM_IS_CLEARINUSE(t) (t->desc->type & AP_SLOTMEM_TYPE_CLEARINUSE)
33
33
34
/* The description of the slots to reuse the slotmem */
34
/* The description of the slots to reuse the slotmem */
35
typedef struct {
35
typedef struct {
Lines 47-70 struct ap_slotmem_instance_t { Link Here
47
    int                  fbased;      /* filebased? */
47
    int                  fbased;      /* filebased? */
48
    void                 *shm;        /* ptr to memory segment (apr_shm_t *) */
48
    void                 *shm;        /* ptr to memory segment (apr_shm_t *) */
49
    void                 *base;       /* data set start */
49
    void                 *base;       /* data set start */
50
    apr_pool_t           *gpool;      /* per segment global pool */
50
    apr_pool_t           *pool;       /* per segment pool (generation cleared) */
51
    char                 *inuse;      /* in-use flag table*/
51
    char                 *inuse;      /* in-use flag table*/
52
    unsigned int         *num_free;   /* slot free count for this instance */
52
    unsigned int         *num_free;   /* slot free count for this instance */
53
    void                 *persist;    /* persist dataset start */
53
    void                 *persist;    /* persist dataset start */
54
    sharedslotdesc_t     desc;        /* per slot desc */
54
    const sharedslotdesc_t *desc;     /* per slot desc */
55
    struct ap_slotmem_instance_t  *next;       /* location of next allocated segment */
55
    struct ap_slotmem_instance_t  *next;       /* location of next allocated segment */
56
};
56
};
57
57
58
/*
58
/*
59
 * Memory layout:
59
 * Layout for SHM and persited file :
60
 *     sharedslotdesc_t | num_free | slots | isuse array |
60
 *
61
 *                      ^          ^
61
 *   +-------------------------------------------------------------+~>
62
 *                      |          . base
62
 *   | desc | num_free | base (slots) | inuse (array) | md5 | desc | compat..
63
 *                      . persist (also num_free)
63
 *   +------+-----------------------------------------+------------+~>
64
 *   ^      ^                                         ^    \ /     ^   :
65
 *   |______|_____________ SHM (mem->@) ______________|     | _____|__/
66
 *          |                                               |/     |
67
 *          |                                         ^     v      |
68
 *          |_____________________ File (mem->persist +  [meta]) __|
64
 */
69
 */
65
70
71
66
/* global pool and list of slotmem we are handling */
72
/* global pool and list of slotmem we are handling */
67
static struct ap_slotmem_instance_t *globallistmem = NULL;
73
static struct ap_slotmem_instance_t *globallistmem = NULL,
74
                                   **retained_globallistmem = NULL;
68
static apr_pool_t *gpool = NULL;
75
static apr_pool_t *gpool = NULL;
69
76
70
#define DEFAULT_SLOTMEM_PREFIX "slotmem-shm-"
77
#define DEFAULT_SLOTMEM_PREFIX "slotmem-shm-"
Lines 71-101 static apr_pool_t *gpool = NULL; Link Here
71
#define DEFAULT_SLOTMEM_SUFFIX ".shm"
78
#define DEFAULT_SLOTMEM_SUFFIX ".shm"
72
#define DEFAULT_SLOTMEM_PERSIST_SUFFIX ".persist"
79
#define DEFAULT_SLOTMEM_PERSIST_SUFFIX ".persist"
73
80
74
/* Unixes (and Netware) have the unlink() semantic, which allows to
75
 * apr_file_remove() a file still in use (opened elsewhere), the inode
76
 * remains until the last fd is closed, whereas any file created with
77
 * the same name/path will use a new inode.
78
 *
79
 * On windows and OS/2 ("\SHAREMEM\..." tree), apr_file_remove() marks
80
 * the files for deletion until the last HANDLE is closed, meanwhile the
81
 * same file/path can't be opened/recreated.
82
 * Thus on graceful restart (the only restart mode with mpm_winnt), the
83
 * old file may still exist until all the children stop, while we ought
84
 * to create a new one for our new clear SHM.  Therefore, we would only
85
 * be able to reuse (attach) the old SHM, preventing some changes to
86
 * the config file, like the number of balancers/members, since the
87
 * size checks (to fit the new config) would fail.  Let's avoid this by
88
 * including the generation number in the SHM filename (obviously not
89
 * the persisted name!)
90
 */
91
#ifndef SLOTMEM_UNLINK_SEMANTIC
92
#if defined(WIN32) || defined(OS2)
93
#define SLOTMEM_UNLINK_SEMANTIC 0
94
#else
95
#define SLOTMEM_UNLINK_SEMANTIC 1
96
#endif
97
#endif
98
99
/*
81
/*
100
 * Persist the slotmem in a file
82
 * Persist the slotmem in a file
101
 * slotmem name and file name.
83
 * slotmem name and file name.
Lines 113-130 static int slotmem_filenames(apr_pool_t *pool, Link Here
113
95
114
    if (slotname && *slotname && strcasecmp(slotname, "none") != 0) {
96
    if (slotname && *slotname && strcasecmp(slotname, "none") != 0) {
115
        if (slotname[0] != '/') {
97
        if (slotname[0] != '/') {
116
#if !SLOTMEM_UNLINK_SEMANTIC
117
            /* Each generation needs its own file name. */
118
            int generation = 0;
119
            ap_mpm_query(AP_MPMQ_GENERATION, &generation);
120
            fname = apr_psprintf(pool, "%s%s_%x%s", DEFAULT_SLOTMEM_PREFIX,
121
                                 slotname, generation, DEFAULT_SLOTMEM_SUFFIX);
122
#else
123
            /* Reuse the same file name for each generation. */
124
            fname = apr_pstrcat(pool, DEFAULT_SLOTMEM_PREFIX,
98
            fname = apr_pstrcat(pool, DEFAULT_SLOTMEM_PREFIX,
125
                                slotname, DEFAULT_SLOTMEM_SUFFIX,
99
                                slotname, DEFAULT_SLOTMEM_SUFFIX,
126
                                NULL);
100
                                NULL);
127
#endif
128
            fname = ap_runtime_dir_relative(pool, fname);
101
            fname = ap_runtime_dir_relative(pool, fname);
129
        }
102
        }
130
        else {
103
        else {
Lines 135-151 static int slotmem_filenames(apr_pool_t *pool, Link Here
135
        }
108
        }
136
109
137
        if (persistname) {
110
        if (persistname) {
138
            /* Persisted file names are immutable... */
139
#if !SLOTMEM_UNLINK_SEMANTIC
140
            if (slotname[0] != '/') {
141
                pname = apr_pstrcat(pool, DEFAULT_SLOTMEM_PREFIX,
142
                                    slotname, DEFAULT_SLOTMEM_SUFFIX,
143
                                    DEFAULT_SLOTMEM_PERSIST_SUFFIX,
144
                                    NULL);
145
                pname = ap_runtime_dir_relative(pool, pname);
146
            }
147
            else
148
#endif
149
            pname = apr_pstrcat(pool, fname,
111
            pname = apr_pstrcat(pool, fname,
150
                                DEFAULT_SLOTMEM_PERSIST_SUFFIX,
112
                                DEFAULT_SLOTMEM_PERSIST_SUFFIX,
151
                                NULL);
113
                                NULL);
Lines 170-176 static void slotmem_clearinuse(ap_slotmem_instance Link Here
170
    
132
    
171
    inuse = slot->inuse;
133
    inuse = slot->inuse;
172
    
134
    
173
    for (i = 0; i < slot->desc.num; i++, inuse++) {
135
    for (i = 0; i < slot->desc->num; i++, inuse++) {
174
        if (*inuse) {
136
        if (*inuse) {
175
            *inuse = 0;
137
            *inuse = 0;
176
            (*slot->num_free)++;
138
            (*slot->num_free)++;
Lines 191-201 static void store_slotmem(ap_slotmem_instance_t *s Link Here
191
153
192
    if (storename) {
154
    if (storename) {
193
        rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE,
155
        rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE,
194
                           APR_OS_DEFAULT, slotmem->gpool);
156
                           APR_OS_DEFAULT, slotmem->pool);
195
        if (APR_STATUS_IS_EEXIST(rv)) {
157
        if (APR_STATUS_IS_EEXIST(rv)) {
196
            apr_file_remove(storename, slotmem->gpool);
158
            apr_file_remove(storename, slotmem->pool);
197
            rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE,
159
            rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE,
198
                               APR_OS_DEFAULT, slotmem->gpool);
160
                               APR_OS_DEFAULT, slotmem->pool);
199
        }
161
        }
200
        if (rv != APR_SUCCESS) {
162
        if (rv != APR_SUCCESS) {
201
            return;
163
            return;
Lines 203-230 static void store_slotmem(ap_slotmem_instance_t *s Link Here
203
        if (AP_SLOTMEM_IS_CLEARINUSE(slotmem)) {
165
        if (AP_SLOTMEM_IS_CLEARINUSE(slotmem)) {
204
            slotmem_clearinuse(slotmem);
166
            slotmem_clearinuse(slotmem);
205
        }
167
        }
206
        nbytes = (slotmem->desc.size * slotmem->desc.num) +
168
        nbytes = (slotmem->desc->size * slotmem->desc->num) +
207
                 (slotmem->desc.num * sizeof(char)) + AP_UNSIGNEDINT_OFFSET;
169
                 (slotmem->desc->num * sizeof(char)) + AP_UNSIGNEDINT_OFFSET;
208
        apr_md5(digest, slotmem->persist, nbytes);
170
        apr_md5(digest, slotmem->persist, nbytes);
209
        rv = apr_file_write_full(fp, slotmem->persist, nbytes, NULL);
171
        rv = apr_file_write_full(fp, slotmem->persist, nbytes, NULL);
210
        if (rv == APR_SUCCESS) {
172
        if (rv == APR_SUCCESS) {
211
            rv = apr_file_write_full(fp, digest, APR_MD5_DIGESTSIZE, NULL);
173
            rv = apr_file_write_full(fp, digest, APR_MD5_DIGESTSIZE, NULL);
212
        }
174
        }
175
        if (rv == APR_SUCCESS) {
176
            rv = apr_file_write_full(fp, slotmem->desc, AP_SLOTMEM_OFFSET,
177
                                     NULL);
178
        }
213
        apr_file_close(fp);
179
        apr_file_close(fp);
214
        if (rv != APR_SUCCESS) {
180
        if (rv != APR_SUCCESS) {
215
            apr_file_remove(storename, slotmem->gpool);
181
            apr_file_remove(storename, slotmem->pool);
216
        }
182
        }
217
    }
183
    }
218
}
184
}
219
185
220
static apr_status_t restore_slotmem(void *ptr, const char *storename,
186
static apr_status_t restore_slotmem(sharedslotdesc_t *desc,
221
                                    apr_size_t size, apr_pool_t *pool)
187
                                    const char *storename, apr_size_t size,
188
                                    apr_pool_t *pool)
222
{
189
{
223
    apr_file_t *fp;
190
    apr_file_t *fp;
224
    apr_size_t nbytes = size;
191
    apr_status_t rv = APR_ENOTIMPL;
225
    apr_status_t rv = APR_SUCCESS;
192
    void *ptr = (char *)desc + AP_SLOTMEM_OFFSET;
193
    apr_size_t dsize = size - AP_SLOTMEM_OFFSET;
194
    apr_size_t nbytes = dsize;
226
    unsigned char digest[APR_MD5_DIGESTSIZE];
195
    unsigned char digest[APR_MD5_DIGESTSIZE];
227
    unsigned char digest2[APR_MD5_DIGESTSIZE];
196
    unsigned char digest2[APR_MD5_DIGESTSIZE];
197
    char desc_buf[AP_SLOTMEM_OFFSET];
228
198
229
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02335)
199
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02335)
230
                 "restoring %s", storename);
200
                 "restoring %s", storename);
Lines 234-240 static void store_slotmem(ap_slotmem_instance_t *s Link Here
234
                           pool);
204
                           pool);
235
        if (rv == APR_SUCCESS) {
205
        if (rv == APR_SUCCESS) {
236
            rv = apr_file_read(fp, ptr, &nbytes);
206
            rv = apr_file_read(fp, ptr, &nbytes);
237
            if ((rv == APR_SUCCESS || rv == APR_EOF) && nbytes == size) {
207
            if ((rv == APR_SUCCESS || rv == APR_EOF) && nbytes == dsize) {
238
                rv = APR_SUCCESS;   /* for successful return @ EOF */
208
                rv = APR_SUCCESS;   /* for successful return @ EOF */
239
                /*
209
                /*
240
                 * if at EOF, don't bother checking md5
210
                 * if at EOF, don't bother checking md5
Lines 243-270 static void store_slotmem(ap_slotmem_instance_t *s Link Here
243
                if (apr_file_eof(fp) != APR_EOF) {
213
                if (apr_file_eof(fp) != APR_EOF) {
244
                    apr_size_t ds = APR_MD5_DIGESTSIZE;
214
                    apr_size_t ds = APR_MD5_DIGESTSIZE;
245
                    rv = apr_file_read(fp, digest, &ds);
215
                    rv = apr_file_read(fp, digest, &ds);
246
                    if ((rv == APR_SUCCESS || rv == APR_EOF) &&
216
                    if ((rv == APR_SUCCESS || rv == APR_EOF)
247
                        ds == APR_MD5_DIGESTSIZE) {
217
                            && ds == APR_MD5_DIGESTSIZE) {
248
                        rv = APR_SUCCESS;
249
                        apr_md5(digest2, ptr, nbytes);
218
                        apr_md5(digest2, ptr, nbytes);
250
                        if (memcmp(digest, digest2, APR_MD5_DIGESTSIZE)) {
219
                        if (memcmp(digest, digest2, APR_MD5_DIGESTSIZE)) {
251
                            ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
220
                            rv = APR_EMISMATCH;
252
                                         APLOGNO(02551) "bad md5 match");
253
                            rv = APR_EGENERAL;
254
                        }
221
                        }
222
                        /*
223
                         * if at EOF, don't bother checking desc
224
                         *  - backwards compatibility
225
                         *  */
226
                        else if (apr_file_eof(fp) != APR_EOF) {
227
                            nbytes = sizeof(desc_buf);
228
                            rv = apr_file_read(fp, desc_buf, &nbytes);
229
                            if ((rv == APR_SUCCESS || rv == APR_EOF)
230
                                    && nbytes == sizeof(desc_buf)) {
231
                                if (memcmp(desc, desc_buf, nbytes)) {
232
                                    rv = APR_EMISMATCH;
233
                                }
234
                                else {
235
                                    rv = APR_SUCCESS;
236
                                }
237
                            }
238
                            else if (rv == APR_SUCCESS || rv == APR_EOF) {
239
                                rv = APR_INCOMPLETE;
240
                            }
241
                        }
242
                        else {
243
                            rv = APR_EOF;
244
                        }
255
                    }
245
                    }
246
                    else if (rv == APR_SUCCESS || rv == APR_EOF) {
247
                        rv = APR_INCOMPLETE;
248
                    }
256
                }
249
                }
257
                else {
250
                else {
258
                    ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
251
                    rv = APR_EOF;
259
                                 APLOGNO(02552) "at EOF... bypassing md5 match check (old persist file?)");
260
                }
252
                }
253
                if (rv == APR_EMISMATCH) {
254
                    ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02551)
255
                                 "persisted slotmem md5/desc mismatch");
256
                }
257
                else if (rv == APR_EOF) {
258
                    ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(02552)
259
                                 "persisted slotmem at EOF... bypassing md5/desc match check "
260
                                 "(old persist file?)");
261
                    rv = APR_SUCCESS;
262
                }
261
            }
263
            }
262
            else if (nbytes != size) {
264
            else if (rv == APR_SUCCESS || rv == APR_EOF) {
263
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
265
                rv = APR_INCOMPLETE;
264
                             APLOGNO(02553) "Expected %" APR_SIZE_T_FMT ": Read %" APR_SIZE_T_FMT,
265
                             size, nbytes);
266
                rv = APR_EGENERAL;
267
            }
266
            }
267
            if (rv == APR_INCOMPLETE) {
268
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02553)
269
                             "persisted slotmem read had unexpected size");
270
            }
268
            apr_file_close(fp);
271
            apr_file_close(fp);
269
        }
272
        }
270
    }
273
    }
Lines 271-296 static void store_slotmem(ap_slotmem_instance_t *s Link Here
271
    return rv;
274
    return rv;
272
}
275
}
273
276
274
static apr_status_t cleanup_slotmem(void *param)
277
static apr_status_t cleanup_slotmem(void *is_startup)
275
{
278
{
276
    ap_slotmem_instance_t **mem = param;
279
    int is_exiting = (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_EXITING);
280
    ap_slotmem_instance_t *mem;
277
281
278
    if (*mem) {
282
    /* When in startup/pre-config's cleanup, the retained data and global pool
279
        ap_slotmem_instance_t *next = *mem;
283
     * are not used yet, but the SHMs contents were untouched hence they don't
280
        while (next) {
284
     * need to be persisted, simply unlink them.
281
            if (AP_SLOTMEM_IS_PERSIST(next)) {
285
     * Otherwise when restarting or stopping we want to flush persisted data,
282
                store_slotmem(next);
286
     * and in the stopping/exiting case we also want to unlink the SHMs.
287
     */
288
    for (mem = globallistmem; mem; mem = mem->next) {
289
        int unlink;
290
        if (is_startup) {
291
            unlink = mem->fbased;
292
        }
293
        else {
294
            if (AP_SLOTMEM_IS_PERSIST(mem)) {
295
                store_slotmem(mem);
283
            }
296
            }
284
            apr_shm_destroy((apr_shm_t *)next->shm);
297
            unlink = is_exiting;
285
            if (next->fbased) {
286
                apr_shm_remove(next->name, next->gpool);
287
                apr_file_remove(next->name, next->gpool);
288
            }
289
            next = next->next;
290
        }
298
        }
299
        if (unlink) {
300
            /* Some systems may require the descriptor to be closed before
301
             * unlink, thus call destroy() first.
302
             */
303
            apr_shm_destroy(mem->shm);
304
            apr_shm_remove(mem->name, mem->pool);
305
        }
291
    }
306
    }
292
    /* apr_pool_destroy(gpool); */
307
308
    if (is_exiting) {
309
        *retained_globallistmem = NULL;
310
    }
311
    else if (!is_startup) {
312
        *retained_globallistmem = globallistmem;
313
    }
293
    globallistmem = NULL;
314
    globallistmem = NULL;
315
294
    return APR_SUCCESS;
316
    return APR_SUCCESS;
295
}
317
}
296
318
Lines 309-326 static apr_status_t slotmem_doall(ap_slotmem_insta Link Here
309
331
310
    ptr = (char *)mem->base;
332
    ptr = (char *)mem->base;
311
    inuse = mem->inuse;
333
    inuse = mem->inuse;
312
    for (i = 0; i < mem->desc.num; i++, inuse++) {
334
    for (i = 0; i < mem->desc->num; i++, inuse++) {
313
        if (!AP_SLOTMEM_IS_PREGRAB(mem) ||
335
        if (!AP_SLOTMEM_IS_PREGRAB(mem) || *inuse) {
314
           (AP_SLOTMEM_IS_PREGRAB(mem) && *inuse)) {
315
            retval = func((void *) ptr, data, pool);
336
            retval = func((void *) ptr, data, pool);
316
            if (retval != APR_SUCCESS)
337
            if (retval != APR_SUCCESS)
317
                break;
338
                break;
318
        }
339
        }
319
        ptr += mem->desc.size;
340
        ptr += mem->desc->size;
320
    }
341
    }
321
    return retval;
342
    return retval;
322
}
343
}
323
344
345
static int check_slotmem(ap_slotmem_instance_t *mem, apr_size_t size,
346
                         apr_size_t item_size, unsigned int item_num)
347
{
348
    sharedslotdesc_t *desc;
349
350
    /* check size */
351
    if (apr_shm_size_get(mem->shm) != size) {
352
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02599)
353
                     "existing shared memory for %s could not be used "
354
                     "(failed size check)",
355
                     mem->name);
356
        return 0;
357
    }
358
359
    desc = apr_shm_baseaddr_get(mem->shm);
360
    if (desc->size != item_size || desc->num != item_num) {
361
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02600)
362
                     "existing shared memory for %s could not be used "
363
                     "(failed contents check)",
364
                     mem->name);
365
        return 0;
366
    }
367
368
    return 1;
369
}
370
324
static apr_status_t slotmem_create(ap_slotmem_instance_t **new,
371
static apr_status_t slotmem_create(ap_slotmem_instance_t **new,
325
                                   const char *name, apr_size_t item_size,
372
                                   const char *name, apr_size_t item_size,
326
                                   unsigned int item_num,
373
                                   unsigned int item_num,
Lines 329-335 static apr_status_t slotmem_create(ap_slotmem_inst Link Here
329
    int fbased = 1;
376
    int fbased = 1;
330
    int restored = 0;
377
    int restored = 0;
331
    char *ptr;
378
    char *ptr;
332
    sharedslotdesc_t desc;
379
    sharedslotdesc_t *desc;
333
    ap_slotmem_instance_t *res;
380
    ap_slotmem_instance_t *res;
334
    ap_slotmem_instance_t *next = globallistmem;
381
    ap_slotmem_instance_t *next = globallistmem;
335
    const char *fname, *pname = NULL;
382
    const char *fname, *pname = NULL;
Lines 339-355 static apr_status_t slotmem_create(ap_slotmem_inst Link Here
339
                      (item_num * sizeof(char)) + basesize;
386
                      (item_num * sizeof(char)) + basesize;
340
    int persist = (type & AP_SLOTMEM_TYPE_PERSIST) != 0;
387
    int persist = (type & AP_SLOTMEM_TYPE_PERSIST) != 0;
341
    apr_status_t rv;
388
    apr_status_t rv;
389
    apr_pool_t *p;
342
390
343
    if (gpool == NULL) {
391
    *new = NULL;
344
        return APR_ENOSHMAVAIL;
392
345
    }
346
    if (slotmem_filenames(pool, name, &fname, persist ? &pname : NULL)) {
393
    if (slotmem_filenames(pool, name, &fname, persist ? &pname : NULL)) {
347
        /* first try to attach to existing slotmem */
394
        /* first try to attach to existing slotmem */
348
        if (next) {
395
        if (next) {
396
            ap_slotmem_instance_t *prev = NULL;
349
            for (;;) {
397
            for (;;) {
350
                if (strcmp(next->name, fname) == 0) {
398
                if (strcmp(next->name, fname) == 0) {
399
                    *new = next; /* either returned here or reused finally */
400
                    if (!check_slotmem(next, size, item_size, item_num)) {
401
                        apr_shm_destroy(next->shm);
402
                        next = next->next;
403
                        if (prev) {
404
                            prev->next = next;
405
                        }
406
                        else {
407
                            globallistmem = next;
408
                        }
409
                        if (next) {
410
                            continue;
411
                        }
412
                        next = prev;
413
                        break;
414
                    }
351
                    /* we already have it */
415
                    /* we already have it */
352
                    *new = next;
353
                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02603)
416
                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02603)
354
                                 "create found %s in global list", fname);
417
                                 "create found %s in global list", fname);
355
                    return APR_SUCCESS;
418
                    return APR_SUCCESS;
Lines 357-362 static apr_status_t slotmem_create(ap_slotmem_inst Link Here
357
                if (!next->next) {
420
                if (!next->next) {
358
                     break;
421
                     break;
359
                }
422
                }
423
                prev = next;
360
                next = next->next;
424
                next = next->next;
361
            }
425
            }
362
        }
426
        }
Lines 372-414 static apr_status_t slotmem_create(ap_slotmem_inst Link Here
372
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02300)
436
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02300)
373
                 "create %s: %"APR_SIZE_T_FMT"/%u", fname, item_size,
437
                 "create %s: %"APR_SIZE_T_FMT"/%u", fname, item_size,
374
                 item_num);
438
                 item_num);
375
    if (fbased) {
376
        rv = apr_shm_attach(&shm, fname, gpool);
377
    }
378
    else {
379
        rv = APR_EINVAL;
380
    }
381
    if (rv == APR_SUCCESS) {
382
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02598)
383
                     "apr_shm_attach() succeeded");
384
439
385
        /* check size */
440
    {
386
        if (apr_shm_size_get(shm) != size) {
387
            apr_shm_detach(shm);
388
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02599)
389
                         "existing shared memory for %s could not be used (failed size check)",
390
                         fname);
391
            return APR_EINVAL;
392
        }
393
        ptr = (char *)apr_shm_baseaddr_get(shm);
394
        memcpy(&desc, ptr, sizeof(desc));
395
        if (desc.size != item_size || desc.num != item_num) {
396
            apr_shm_detach(shm);
397
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02600)
398
                         "existing shared memory for %s could not be used (failed contents check)",
399
                         fname);
400
            return APR_EINVAL;
401
        }
402
        ptr += AP_SLOTMEM_OFFSET;
403
    }
404
    else {
405
        apr_size_t dsize = size - AP_SLOTMEM_OFFSET;
406
        if (fbased) {
441
        if (fbased) {
407
            apr_shm_remove(fname, gpool);
442
            apr_shm_remove(fname, pool);
408
            rv = apr_shm_create(&shm, size, fname, gpool);
443
            rv = apr_shm_create(&shm, size, fname, gpool);
409
        }
444
        }
410
        else {
445
        else {
411
            rv = apr_shm_create(&shm, size, NULL, gpool);
446
            rv = apr_shm_create(&shm, size, NULL, pool);
412
        }
447
        }
413
        ap_log_error(APLOG_MARK, rv == APR_SUCCESS ? APLOG_DEBUG : APLOG_ERR,
448
        ap_log_error(APLOG_MARK, rv == APR_SUCCESS ? APLOG_DEBUG : APLOG_ERR,
414
                     rv, ap_server_conf, APLOGNO(02611)
449
                     rv, ap_server_conf, APLOGNO(02611)
Lines 418-474 static apr_status_t slotmem_create(ap_slotmem_inst Link Here
418
        if (rv != APR_SUCCESS) {
453
        if (rv != APR_SUCCESS) {
419
            return rv;
454
            return rv;
420
        }
455
        }
421
        ptr = (char *)apr_shm_baseaddr_get(shm);
456
422
        desc.size = item_size;
457
        desc = (sharedslotdesc_t *)apr_shm_baseaddr_get(shm);
423
        desc.num = item_num;
458
        memset(desc, 0, size);
424
        desc.type = type;
459
        desc->size = item_size;
425
        memcpy(ptr, &desc, sizeof(desc));
460
        desc->num = item_num;
426
        ptr += AP_SLOTMEM_OFFSET;
461
        desc->type = type;
427
        memset(ptr, 0, dsize);
462
428
        /*
463
        /*
429
         * TODO: Error check the below... What error makes
464
         * TODO: Error check the below... What error makes
430
         * sense if the restore fails? Any?
465
         * sense if the restore fails? Any?
466
         * For now, we continue with a fresh new slotmem,
467
         * but NOTICE in the log.
431
         */
468
         */
432
        if (persist) {
469
        if (persist) {
433
            rv = restore_slotmem(ptr, pname, dsize, pool);
470
            rv = restore_slotmem(desc, pname, size, pool);
434
            if (rv == APR_SUCCESS) {
471
            if (rv == APR_SUCCESS) {
435
                restored = 1;
472
                restored = 1;
436
            }
473
            }
437
            else {
474
            else {
438
                /* just in case, re-zero */
475
                /* just in case, re-zero */
439
                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
476
                ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
440
                             APLOGNO(02554) "could not restore %s", fname);
477
                             APLOGNO(02554) "could not restore %s", fname);
441
                memset(ptr, 0, dsize);
478
                memset((char *)desc + AP_SLOTMEM_OFFSET, 0,
479
                       size - AP_SLOTMEM_OFFSET);
442
            }
480
            }
443
        }
481
        }
444
    }
482
    }
445
483
446
    /* For the chained slotmem stuff */
484
    p = fbased ? gpool : pool;
447
    res = (ap_slotmem_instance_t *) apr_pcalloc(gpool,
485
    ptr = (char *)desc + AP_SLOTMEM_OFFSET;
448
                                                sizeof(ap_slotmem_instance_t));
486
449
    res->name = apr_pstrdup(gpool, fname);
487
    /* For the chained slotmem stuff (*new may be reused from above) */
450
    res->pname = apr_pstrdup(gpool, pname);
488
    res = *new;
489
    if (res == NULL) {
490
        res = apr_pcalloc(p, sizeof(ap_slotmem_instance_t));
491
        res->name = apr_pstrdup(p, fname);
492
        res->pname = apr_pstrdup(p, pname);
493
        *new = res;
494
    }
451
    res->fbased = fbased;
495
    res->fbased = fbased;
452
    res->shm = shm;
496
    res->shm = shm;
497
    res->persist = (void *)ptr;
453
    res->num_free = (unsigned int *)ptr;
498
    res->num_free = (unsigned int *)ptr;
499
    ptr += AP_UNSIGNEDINT_OFFSET;
454
    if (!restored) {
500
    if (!restored) {
455
        *res->num_free = item_num;
501
        *res->num_free = item_num;
456
    }
502
    }
457
    res->persist = (void *)ptr;
458
    ptr += AP_UNSIGNEDINT_OFFSET;
459
    res->base = (void *)ptr;
503
    res->base = (void *)ptr;
460
    res->desc = desc;
504
    res->desc = desc;
461
    res->gpool = gpool;
505
    res->pool = pool;
462
    res->next = NULL;
506
    res->next = NULL;
463
    res->inuse = ptr + basesize;
507
    res->inuse = ptr + basesize;
464
    if (globallistmem == NULL) {
508
    if (fbased) {
465
        globallistmem = res;
509
        if (globallistmem == NULL) {
510
            globallistmem = res;
511
        }
512
        else {
513
            next->next = res;
514
        }
466
    }
515
    }
467
    else {
468
        next->next = res;
469
    }
470
516
471
    *new = res;
472
    return APR_SUCCESS;
517
    return APR_SUCCESS;
473
}
518
}
474
519
Lines 480-493 static apr_status_t slotmem_attach(ap_slotmem_inst Link Here
480
    char *ptr;
525
    char *ptr;
481
    ap_slotmem_instance_t *res;
526
    ap_slotmem_instance_t *res;
482
    ap_slotmem_instance_t *next = globallistmem;
527
    ap_slotmem_instance_t *next = globallistmem;
483
    sharedslotdesc_t desc;
528
    sharedslotdesc_t *desc;
484
    const char *fname;
529
    const char *fname;
485
    apr_shm_t *shm;
530
    apr_shm_t *shm;
486
    apr_status_t rv;
531
    apr_status_t rv;
487
532
488
    if (gpool == NULL) {
489
        return APR_ENOSHMAVAIL;
490
    }
491
    if (!slotmem_filenames(pool, name, &fname, NULL)) {
533
    if (!slotmem_filenames(pool, name, &fname, NULL)) {
492
        return APR_ENOSHMAVAIL;
534
        return APR_ENOSHMAVAIL;
493
    }
535
    }
Lines 501-508 static apr_status_t slotmem_attach(ap_slotmem_inst Link Here
501
            if (strcmp(next->name, fname) == 0) {
543
            if (strcmp(next->name, fname) == 0) {
502
                /* we already have it */
544
                /* we already have it */
503
                *new = next;
545
                *new = next;
504
                *item_size = next->desc.size;
546
                *item_size = next->desc->size;
505
                *item_num = next->desc.num;
547
                *item_num = next->desc->num;
506
                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
548
                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
507
                             APLOGNO(02302)
549
                             APLOGNO(02302)
508
                             "attach found %s: %"APR_SIZE_T_FMT"/%u", fname,
550
                             "attach found %s: %"APR_SIZE_T_FMT"/%u", fname,
Lines 517-556 static apr_status_t slotmem_attach(ap_slotmem_inst Link Here
517
    }
559
    }
518
560
519
    /* next try to attach to existing shared memory */
561
    /* next try to attach to existing shared memory */
520
    rv = apr_shm_attach(&shm, fname, gpool);
562
    rv = apr_shm_attach(&shm, fname, pool);
521
    if (rv != APR_SUCCESS) {
563
    if (rv != APR_SUCCESS) {
522
        return rv;
564
        return rv;
523
    }
565
    }
524
566
525
    /* Read the description of the slotmem */
567
    /* Read the description of the slotmem */
526
    ptr = (char *)apr_shm_baseaddr_get(shm);
568
    desc = (sharedslotdesc_t *)apr_shm_baseaddr_get(shm);
527
    memcpy(&desc, ptr, sizeof(desc));
569
    ptr = (char *)desc + AP_SLOTMEM_OFFSET;
528
    ptr += AP_SLOTMEM_OFFSET;
529
570
530
    /* For the chained slotmem stuff */
571
    /* For the chained slotmem stuff */
531
    res = (ap_slotmem_instance_t *) apr_pcalloc(gpool,
572
    res = apr_pcalloc(pool, sizeof(ap_slotmem_instance_t));
532
                                                sizeof(ap_slotmem_instance_t));
573
    res->name = apr_pstrdup(pool, fname);
533
    res->name = apr_pstrdup(gpool, fname);
534
    res->fbased = 1;
574
    res->fbased = 1;
535
    res->shm = shm;
575
    res->shm = shm;
576
    res->persist = (void *)ptr;
536
    res->num_free = (unsigned int *)ptr;
577
    res->num_free = (unsigned int *)ptr;
537
    res->persist = (void *)ptr;
538
    ptr += AP_UNSIGNEDINT_OFFSET;
578
    ptr += AP_UNSIGNEDINT_OFFSET;
539
    res->base = (void *)ptr;
579
    res->base = (void *)ptr;
540
    res->desc = desc;
580
    res->desc = desc;
541
    res->gpool = gpool;
581
    res->pool = pool;
542
    res->inuse = ptr + (desc.size * desc.num);
582
    res->inuse = ptr + (desc->size * desc->num);
543
    res->next = NULL;
583
    res->next = NULL;
544
    if (globallistmem == NULL) {
545
        globallistmem = res;
546
    }
547
    else {
548
        next->next = res;
549
    }
550
584
551
    *new = res;
585
    *new = res;
552
    *item_size = desc.size;
586
    *item_size = desc->size;
553
    *item_num = desc.num;
587
    *item_num = desc->num;
554
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
588
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
555
                 APLOGNO(02303)
589
                 APLOGNO(02303)
556
                 "attach found %s: %"APR_SIZE_T_FMT"/%u", fname,
590
                 "attach found %s: %"APR_SIZE_T_FMT"/%u", fname,
Lines 566-576 static apr_status_t slotmem_dptr(ap_slotmem_instan Link Here
566
    if (!slot) {
600
    if (!slot) {
567
        return APR_ENOSHMAVAIL;
601
        return APR_ENOSHMAVAIL;
568
    }
602
    }
569
    if (id >= slot->desc.num) {
603
    if (id >= slot->desc->num) {
570
        return APR_EINVAL;
604
        return APR_EINVAL;
571
    }
605
    }
572
606
573
    ptr = (char *)slot->base + slot->desc.size * id;
607
    ptr = (char *)slot->base + slot->desc->size * id;
574
    if (!ptr) {
608
    if (!ptr) {
575
        return APR_ENOSHMAVAIL;
609
        return APR_ENOSHMAVAIL;
576
    }
610
    }
Lines 590-596 static apr_status_t slotmem_get(ap_slotmem_instanc Link Here
590
    }
624
    }
591
625
592
    inuse = slot->inuse + id;
626
    inuse = slot->inuse + id;
593
    if (id >= slot->desc.num) {
627
    if (id >= slot->desc->num) {
594
        return APR_EINVAL;
628
        return APR_EINVAL;
595
    }
629
    }
596
    if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) {
630
    if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) {
Lines 617-623 static apr_status_t slotmem_put(ap_slotmem_instanc Link Here
617
    }
651
    }
618
652
619
    inuse = slot->inuse + id;
653
    inuse = slot->inuse + id;
620
    if (id >= slot->desc.num) {
654
    if (id >= slot->desc->num) {
621
        return APR_EINVAL;
655
        return APR_EINVAL;
622
    }
656
    }
623
    if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) {
657
    if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) {
Lines 634-640 static apr_status_t slotmem_put(ap_slotmem_instanc Link Here
634
668
635
static unsigned int slotmem_num_slots(ap_slotmem_instance_t *slot)
669
static unsigned int slotmem_num_slots(ap_slotmem_instance_t *slot)
636
{
670
{
637
    return slot->desc.num;
671
    return slot->desc->num;
638
}
672
}
639
673
640
static unsigned int slotmem_num_free_slots(ap_slotmem_instance_t *slot)
674
static unsigned int slotmem_num_free_slots(ap_slotmem_instance_t *slot)
Lines 644-650 static unsigned int slotmem_num_free_slots(ap_slot Link Here
644
    else {
678
    else {
645
        unsigned int i, counter=0;
679
        unsigned int i, counter=0;
646
        char *inuse = slot->inuse;
680
        char *inuse = slot->inuse;
647
        for (i=0; i<slot->desc.num; i++, inuse++) {
681
        for (i=0; i<slot->desc->num; i++, inuse++) {
648
            if (!*inuse)
682
            if (!*inuse)
649
                counter++;
683
                counter++;
650
        }
684
        }
Lines 654-660 static unsigned int slotmem_num_free_slots(ap_slot Link Here
654
688
655
static apr_size_t slotmem_slot_size(ap_slotmem_instance_t *slot)
689
static apr_size_t slotmem_slot_size(ap_slotmem_instance_t *slot)
656
{
690
{
657
    return slot->desc.size;
691
    return slot->desc->size;
658
}
692
}
659
693
660
static apr_status_t slotmem_grab(ap_slotmem_instance_t *slot, unsigned int *id)
694
static apr_status_t slotmem_grab(ap_slotmem_instance_t *slot, unsigned int *id)
Lines 668-679 static apr_status_t slotmem_grab(ap_slotmem_instan Link Here
668
702
669
    inuse = slot->inuse;
703
    inuse = slot->inuse;
670
704
671
    for (i = 0; i < slot->desc.num; i++, inuse++) {
705
    for (i = 0; i < slot->desc->num; i++, inuse++) {
672
        if (!*inuse) {
706
        if (!*inuse) {
673
            break;
707
            break;
674
        }
708
        }
675
    }
709
    }
676
    if (i >= slot->desc.num) {
710
    if (i >= slot->desc->num) {
677
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02293)
711
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02293)
678
                     "slotmem(%s) grab failed. Num %u/num_free %u",
712
                     "slotmem(%s) grab failed. Num %u/num_free %u",
679
                     slot->name, slotmem_num_slots(slot),
713
                     slot->name, slotmem_num_slots(slot),
Lines 694-700 static apr_status_t slotmem_fgrab(ap_slotmem_insta Link Here
694
        return APR_ENOSHMAVAIL;
728
        return APR_ENOSHMAVAIL;
695
    }
729
    }
696
730
697
    if (id >= slot->desc.num) {
731
    if (id >= slot->desc->num) {
698
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02397)
732
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02397)
699
                     "slotmem(%s) fgrab failed. Num %u/num_free %u",
733
                     "slotmem(%s) fgrab failed. Num %u/num_free %u",
700
                     slot->name, slotmem_num_slots(slot),
734
                     slot->name, slotmem_num_slots(slot),
Lines 721-732 static apr_status_t slotmem_release(ap_slotmem_ins Link Here
721
755
722
    inuse = slot->inuse;
756
    inuse = slot->inuse;
723
757
724
    if (id >= slot->desc.num || !inuse[id] ) {
758
    if (id >= slot->desc->num || !inuse[id] ) {
725
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02294)
759
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02294)
726
                     "slotmem(%s) release failed. Num %u/inuse[%u] %d",
760
                     "slotmem(%s) release failed. Num %u/inuse[%u] %d",
727
                     slot->name, slotmem_num_slots(slot),
761
                     slot->name, slotmem_num_slots(slot),
728
                     id, (int)inuse[id]);
762
                     id, (int)inuse[id]);
729
        if (id >= slot->desc.num) {
763
        if (id >= slot->desc->num) {
730
            return APR_EINVAL;
764
            return APR_EINVAL;
731
        } else {
765
        } else {
732
            return APR_NOTFOUND;
766
            return APR_NOTFOUND;
Lines 759-800 static const ap_slotmem_provider_t *slotmem_shm_ge Link Here
759
    return (&storage);
793
    return (&storage);
760
}
794
}
761
795
762
/* initialise the global pool */
796
/* Initialize or reuse the retained slotmems list, and register the
763
static void slotmem_shm_initgpool(apr_pool_t *p)
797
 * cleanup to make sure the persisted SHMs are stored and the retained
798
 * data are up to date on next restart/stop.
799
 */
800
static int pre_config(apr_pool_t *pconf, apr_pool_t *plog,
801
                      apr_pool_t *ptemp)
764
{
802
{
765
    gpool = p;
803
    void *is_startup = NULL;
766
}
804
    const char *retained_key = "mod_slotmem_shm";
767
805
768
/* Add the pool_clean routine */
806
    retained_globallistmem = ap_retained_data_get(retained_key);
769
static void slotmem_shm_initialize_cleanup(apr_pool_t *p)
807
    if (!retained_globallistmem) {
770
{
808
        retained_globallistmem =
771
    apr_pool_cleanup_register(p, &globallistmem, cleanup_slotmem,
809
            ap_retained_data_create(retained_key,
810
                                    sizeof *retained_globallistmem);
811
    }
812
    globallistmem = *retained_globallistmem;
813
814
    if (ap_state_query(AP_SQ_MAIN_STATE) != AP_SQ_MS_CREATE_PRE_CONFIG) {
815
        gpool = ap_pglobal;
816
    }
817
    else {
818
        is_startup = (void *)1;
819
        gpool = pconf;
820
    }
821
822
    apr_pool_cleanup_register(pconf, is_startup, cleanup_slotmem,
772
                              apr_pool_cleanup_null);
823
                              apr_pool_cleanup_null);
773
}
774
824
775
/*
776
 * Make sure the shared memory is cleaned
777
 */
778
static int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
779
                       server_rec *s)
780
{
781
    slotmem_shm_initialize_cleanup(p);
782
    return OK;
825
    return OK;
783
}
826
}
784
827
785
static int pre_config(apr_pool_t *p, apr_pool_t *plog,
786
                      apr_pool_t *ptemp)
787
{
788
    slotmem_shm_initgpool(p);
789
    return OK;
790
}
791
792
static void ap_slotmem_shm_register_hook(apr_pool_t *p)
828
static void ap_slotmem_shm_register_hook(apr_pool_t *p)
793
{
829
{
794
    const ap_slotmem_provider_t *storage = slotmem_shm_getstorage();
830
    const ap_slotmem_provider_t *storage = slotmem_shm_getstorage();
795
    ap_register_provider(p, AP_SLOTMEM_PROVIDER_GROUP, "shm",
831
    ap_register_provider(p, AP_SLOTMEM_PROVIDER_GROUP, "shm",
796
                         AP_SLOTMEM_PROVIDER_VERSION, storage);
832
                         AP_SLOTMEM_PROVIDER_VERSION, storage);
797
    ap_hook_post_config(post_config, NULL, NULL, APR_HOOK_LAST);
798
    ap_hook_pre_config(pre_config, NULL, NULL, APR_HOOK_MIDDLE);
833
    ap_hook_pre_config(pre_config, NULL, NULL, APR_HOOK_MIDDLE);
799
}
834
}
800
835

Return to bug 62044