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

(-)modules/slotmem/mod_slotmem_shm.c (-203 / +194 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-57 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
Lines 64-70 struct ap_slotmem_instance_t { Link Here
64
 */
64
 */
65
65
66
/* global pool and list of slotmem we are handling */
66
/* global pool and list of slotmem we are handling */
67
static struct ap_slotmem_instance_t *globallistmem = NULL;
67
static struct ap_slotmem_instance_t *globallistmem = NULL,
68
                                   **retained_globallistmem = NULL;
68
static apr_pool_t *gpool = NULL;
69
static apr_pool_t *gpool = NULL;
69
70
70
#define DEFAULT_SLOTMEM_PREFIX "slotmem-shm-"
71
#define DEFAULT_SLOTMEM_PREFIX "slotmem-shm-"
Lines 71-101 static apr_pool_t *gpool = NULL; Link Here
71
#define DEFAULT_SLOTMEM_SUFFIX ".shm"
72
#define DEFAULT_SLOTMEM_SUFFIX ".shm"
72
#define DEFAULT_SLOTMEM_PERSIST_SUFFIX ".persist"
73
#define DEFAULT_SLOTMEM_PERSIST_SUFFIX ".persist"
73
74
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
/*
75
/*
100
 * Persist the slotmem in a file
76
 * Persist the slotmem in a file
101
 * slotmem name and file name.
77
 * slotmem name and file name.
Lines 113-130 static int slotmem_filenames(apr_pool_t *pool, Link Here
113
89
114
    if (slotname && *slotname && strcasecmp(slotname, "none") != 0) {
90
    if (slotname && *slotname && strcasecmp(slotname, "none") != 0) {
115
        if (slotname[0] != '/') {
91
        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,
92
            fname = apr_pstrcat(pool, DEFAULT_SLOTMEM_PREFIX,
125
                                slotname, DEFAULT_SLOTMEM_SUFFIX,
93
                                slotname, DEFAULT_SLOTMEM_SUFFIX,
126
                                NULL);
94
                                NULL);
127
#endif
128
            fname = ap_runtime_dir_relative(pool, fname);
95
            fname = ap_runtime_dir_relative(pool, fname);
129
        }
96
        }
130
        else {
97
        else {
Lines 135-151 static int slotmem_filenames(apr_pool_t *pool, Link Here
135
        }
102
        }
136
103
137
        if (persistname) {
104
        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,
105
            pname = apr_pstrcat(pool, fname,
150
                                DEFAULT_SLOTMEM_PERSIST_SUFFIX,
106
                                DEFAULT_SLOTMEM_PERSIST_SUFFIX,
151
                                NULL);
107
                                NULL);
Lines 170-176 static void slotmem_clearinuse(ap_slotmem_instance Link Here
170
    
126
    
171
    inuse = slot->inuse;
127
    inuse = slot->inuse;
172
    
128
    
173
    for (i = 0; i < slot->desc.num; i++, inuse++) {
129
    for (i = 0; i < slot->desc->num; i++, inuse++) {
174
        if (*inuse) {
130
        if (*inuse) {
175
            *inuse = 0;
131
            *inuse = 0;
176
            (*slot->num_free)++;
132
            (*slot->num_free)++;
Lines 191-201 static void store_slotmem(ap_slotmem_instance_t *s Link Here
191
147
192
    if (storename) {
148
    if (storename) {
193
        rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE,
149
        rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE,
194
                           APR_OS_DEFAULT, slotmem->gpool);
150
                           APR_OS_DEFAULT, slotmem->pool);
195
        if (APR_STATUS_IS_EEXIST(rv)) {
151
        if (APR_STATUS_IS_EEXIST(rv)) {
196
            apr_file_remove(storename, slotmem->gpool);
152
            apr_file_remove(storename, slotmem->pool);
197
            rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE,
153
            rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE,
198
                               APR_OS_DEFAULT, slotmem->gpool);
154
                               APR_OS_DEFAULT, slotmem->pool);
199
        }
155
        }
200
        if (rv != APR_SUCCESS) {
156
        if (rv != APR_SUCCESS) {
201
            return;
157
            return;
Lines 203-230 static void store_slotmem(ap_slotmem_instance_t *s Link Here
203
        if (AP_SLOTMEM_IS_CLEARINUSE(slotmem)) {
159
        if (AP_SLOTMEM_IS_CLEARINUSE(slotmem)) {
204
            slotmem_clearinuse(slotmem);
160
            slotmem_clearinuse(slotmem);
205
        }
161
        }
206
        nbytes = (slotmem->desc.size * slotmem->desc.num) +
162
        nbytes = (slotmem->desc->size * slotmem->desc->num) +
207
                 (slotmem->desc.num * sizeof(char)) + AP_UNSIGNEDINT_OFFSET;
163
                 (slotmem->desc->num * sizeof(char)) + AP_UNSIGNEDINT_OFFSET;
208
        apr_md5(digest, slotmem->persist, nbytes);
164
        apr_md5(digest, slotmem->persist, nbytes);
209
        rv = apr_file_write_full(fp, slotmem->persist, nbytes, NULL);
165
        rv = apr_file_write_full(fp, slotmem->persist, nbytes, NULL);
210
        if (rv == APR_SUCCESS) {
166
        if (rv == APR_SUCCESS) {
211
            rv = apr_file_write_full(fp, digest, APR_MD5_DIGESTSIZE, NULL);
167
            rv = apr_file_write_full(fp, digest, APR_MD5_DIGESTSIZE, NULL);
212
        }
168
        }
169
        if (rv == APR_SUCCESS) {
170
            rv = apr_file_write_full(fp, slotmem->desc, AP_SLOTMEM_OFFSET,
171
                                     NULL);
172
        }
213
        apr_file_close(fp);
173
        apr_file_close(fp);
214
        if (rv != APR_SUCCESS) {
174
        if (rv != APR_SUCCESS) {
215
            apr_file_remove(storename, slotmem->gpool);
175
            apr_file_remove(storename, slotmem->pool);
216
        }
176
        }
217
    }
177
    }
218
}
178
}
219
179
220
static apr_status_t restore_slotmem(void *ptr, const char *storename,
180
static apr_status_t restore_slotmem(sharedslotdesc_t *desc,
221
                                    apr_size_t size, apr_pool_t *pool)
181
                                    const char *storename, apr_size_t size,
182
                                    apr_pool_t *pool)
222
{
183
{
223
    apr_file_t *fp;
184
    apr_file_t *fp;
224
    apr_size_t nbytes = size;
185
    apr_status_t rv = APR_ENOTIMPL;
225
    apr_status_t rv = APR_SUCCESS;
226
    unsigned char digest[APR_MD5_DIGESTSIZE];
186
    unsigned char digest[APR_MD5_DIGESTSIZE];
227
    unsigned char digest2[APR_MD5_DIGESTSIZE];
187
    unsigned char digest2[APR_MD5_DIGESTSIZE];
188
    char aligned_desc[AP_SLOTMEM_OFFSET];
189
    void *ptr = (char *)desc + AP_SLOTMEM_OFFSET;
190
    apr_size_t dsize = size - AP_SLOTMEM_OFFSET;
191
    apr_size_t nbytes = dsize;
228
192
229
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02335)
193
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02335)
230
                 "restoring %s", storename);
194
                 "restoring %s", storename);
Lines 234-240 static void store_slotmem(ap_slotmem_instance_t *s Link Here
234
                           pool);
198
                           pool);
235
        if (rv == APR_SUCCESS) {
199
        if (rv == APR_SUCCESS) {
236
            rv = apr_file_read(fp, ptr, &nbytes);
200
            rv = apr_file_read(fp, ptr, &nbytes);
237
            if ((rv == APR_SUCCESS || rv == APR_EOF) && nbytes == size) {
201
            if ((rv == APR_SUCCESS || rv == APR_EOF) && nbytes == dsize) {
238
                rv = APR_SUCCESS;   /* for successful return @ EOF */
202
                rv = APR_SUCCESS;   /* for successful return @ EOF */
239
                /*
203
                /*
240
                 * if at EOF, don't bother checking md5
204
                 * 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) {
207
                if (apr_file_eof(fp) != APR_EOF) {
244
                    apr_size_t ds = APR_MD5_DIGESTSIZE;
208
                    apr_size_t ds = APR_MD5_DIGESTSIZE;
245
                    rv = apr_file_read(fp, digest, &ds);
209
                    rv = apr_file_read(fp, digest, &ds);
246
                    if ((rv == APR_SUCCESS || rv == APR_EOF) &&
210
                    if ((rv == APR_SUCCESS || rv == APR_EOF)
247
                        ds == APR_MD5_DIGESTSIZE) {
211
                            && ds == APR_MD5_DIGESTSIZE) {
248
                        rv = APR_SUCCESS;
249
                        apr_md5(digest2, ptr, nbytes);
212
                        apr_md5(digest2, ptr, nbytes);
250
                        if (memcmp(digest, digest2, APR_MD5_DIGESTSIZE)) {
213
                        if (memcmp(digest, digest2, APR_MD5_DIGESTSIZE)) {
251
                            ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
214
                            rv = APR_EMISMATCH;
252
                                         APLOGNO(02551) "bad md5 match");
253
                            rv = APR_EGENERAL;
254
                        }
215
                        }
216
                        /*
217
                         * if at EOF, don't bother checking desc
218
                         *  - backwards compatibility
219
                         *  */
220
                        else if (apr_file_eof(fp) != APR_EOF) {
221
                            nbytes = sizeof(aligned_desc);
222
                            rv = apr_file_read(fp, aligned_desc, &nbytes);
223
                            if ((rv == APR_SUCCESS || rv == APR_EOF)
224
                                    && nbytes == sizeof(aligned_desc)) {
225
                                if (memcmp(desc, aligned_desc,
226
                                           sizeof(aligned_desc))) {
227
                                    rv = APR_EMISMATCH;
228
                                }
229
                                else {
230
                                    rv = APR_SUCCESS;
231
                                }
232
                            }
233
                            else if (rv == APR_SUCCESS || rv == APR_EOF) {
234
                                rv = APR_INCOMPLETE;
235
                            }
236
                        }
237
                        else {
238
                            rv = APR_EOF;
239
                        }
255
                    }
240
                    }
241
                    else if (rv == APR_SUCCESS || rv == APR_EOF) {
242
                        rv = APR_INCOMPLETE;
243
                    }
256
                }
244
                }
257
                else {
245
                else {
258
                    ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
246
                    rv = APR_EOF;
259
                                 APLOGNO(02552) "at EOF... bypassing md5 match check (old persist file?)");
260
                }
247
                }
248
                if (rv == APR_EMISMATCH) {
249
                    ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02551)
250
                                 "persisted slotmem md5/desc mismatch");
251
                }
252
                else if (rv == APR_EOF) {
253
                    ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(02552)
254
                                 "persisted slotmem at EOF... bypassing md5/desc match check "
255
                                 "(old persist file?)");
256
                    rv = APR_SUCCESS;
257
                }
261
            }
258
            }
262
            else if (nbytes != size) {
259
            else if (rv == APR_SUCCESS || rv == APR_EOF) {
263
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
260
                rv = APR_INCOMPLETE;
264
                             APLOGNO(02553) "Expected %" APR_SIZE_T_FMT ": Read %" APR_SIZE_T_FMT,
265
                             size, nbytes);
266
                rv = APR_EGENERAL;
267
            }
261
            }
262
            if (rv == APR_INCOMPLETE) {
263
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02553)
264
                             "persisted slotmem read had unexpected size");
265
            }
268
            apr_file_close(fp);
266
            apr_file_close(fp);
269
        }
267
        }
270
    }
268
    }
Lines 271-296 static void store_slotmem(ap_slotmem_instance_t *s Link Here
271
    return rv;
269
    return rv;
272
}
270
}
273
271
274
static apr_status_t cleanup_slotmem(void *param)
272
static apr_status_t cleanup_slotmem(void *is_startup)
275
{
273
{
276
    ap_slotmem_instance_t **mem = param;
274
    int is_exiting = (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_EXITING);
275
    ap_slotmem_instance_t *mem;
277
276
278
    if (*mem) {
277
    /* When in startup/pre-config's cleanup, the retained data and global pool
279
        ap_slotmem_instance_t *next = *mem;
278
     * are not used yet, but the SHMs contents were untouched hence they don't
280
        while (next) {
279
     * need to be persisted, simply unlink them.
281
            if (AP_SLOTMEM_IS_PERSIST(next)) {
280
     * Otherwise when restarting or stopping we want to flush persisted data,
282
                store_slotmem(next);
281
     * and in the stopping/exiting case we also want to unlink the SHMs.
282
     */
283
    for (mem = globallistmem; mem; mem = mem->next) {
284
        int unlink;
285
        if (is_startup) {
286
            unlink = mem->fbased;
287
        }
288
        else {
289
            if (AP_SLOTMEM_IS_PERSIST(mem)) {
290
                store_slotmem(mem);
283
            }
291
            }
284
            apr_shm_destroy((apr_shm_t *)next->shm);
292
            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
        }
293
        }
294
        if (unlink) {
295
            /* Some systems may require the descriptor to be closed before
296
             * unlink, thus call destroy() first (this won't free mem->shm
297
             * so it's safe to call delete() afterward).
298
             */
299
            apr_shm_destroy(mem->shm);
300
            apr_shm_delete(mem->shm);
301
        }
291
    }
302
    }
292
    /* apr_pool_destroy(gpool); */
303
304
    if (is_exiting) {
305
        *retained_globallistmem = NULL;
306
    }
307
    else if (!is_startup) {
308
        *retained_globallistmem = globallistmem;
309
    }
293
    globallistmem = NULL;
310
    globallistmem = NULL;
311
294
    return APR_SUCCESS;
312
    return APR_SUCCESS;
295
}
313
}
296
314
Lines 309-315 static apr_status_t slotmem_doall(ap_slotmem_insta Link Here
309
327
310
    ptr = (char *)mem->base;
328
    ptr = (char *)mem->base;
311
    inuse = mem->inuse;
329
    inuse = mem->inuse;
312
    for (i = 0; i < mem->desc.num; i++, inuse++) {
330
    for (i = 0; i < mem->desc->num; i++, inuse++) {
313
        if (!AP_SLOTMEM_IS_PREGRAB(mem) ||
331
        if (!AP_SLOTMEM_IS_PREGRAB(mem) ||
314
           (AP_SLOTMEM_IS_PREGRAB(mem) && *inuse)) {
332
           (AP_SLOTMEM_IS_PREGRAB(mem) && *inuse)) {
315
            retval = func((void *) ptr, data, pool);
333
            retval = func((void *) ptr, data, pool);
Lines 316-322 static apr_status_t slotmem_doall(ap_slotmem_insta Link Here
316
            if (retval != APR_SUCCESS)
334
            if (retval != APR_SUCCESS)
317
                break;
335
                break;
318
        }
336
        }
319
        ptr += mem->desc.size;
337
        ptr += mem->desc->size;
320
    }
338
    }
321
    return retval;
339
    return retval;
322
}
340
}
Lines 329-335 static apr_status_t slotmem_create(ap_slotmem_inst Link Here
329
    int fbased = 1;
347
    int fbased = 1;
330
    int restored = 0;
348
    int restored = 0;
331
    char *ptr;
349
    char *ptr;
332
    sharedslotdesc_t desc;
350
    sharedslotdesc_t *desc;
333
    ap_slotmem_instance_t *res;
351
    ap_slotmem_instance_t *res;
334
    ap_slotmem_instance_t *next = globallistmem;
352
    ap_slotmem_instance_t *next = globallistmem;
335
    const char *fname, *pname = NULL;
353
    const char *fname, *pname = NULL;
Lines 339-348 static apr_status_t slotmem_create(ap_slotmem_inst Link Here
339
                      (item_num * sizeof(char)) + basesize;
357
                      (item_num * sizeof(char)) + basesize;
340
    int persist = (type & AP_SLOTMEM_TYPE_PERSIST) != 0;
358
    int persist = (type & AP_SLOTMEM_TYPE_PERSIST) != 0;
341
    apr_status_t rv;
359
    apr_status_t rv;
360
    apr_pool_t *p;
342
361
343
    if (gpool == NULL) {
344
        return APR_ENOSHMAVAIL;
345
    }
346
    if (slotmem_filenames(pool, name, &fname, persist ? &pname : NULL)) {
362
    if (slotmem_filenames(pool, name, &fname, persist ? &pname : NULL)) {
347
        /* first try to attach to existing slotmem */
363
        /* first try to attach to existing slotmem */
348
        if (next) {
364
        if (next) {
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)
388
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02300)
373
                 "create %s: %"APR_SIZE_T_FMT"/%u", fname, item_size,
389
                 "create %s: %"APR_SIZE_T_FMT"/%u", fname, item_size,
374
                 item_num);
390
                 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
391
385
        /* check size */
392
386
        if (apr_shm_size_get(shm) != size) {
393
    {
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) {
394
        if (fbased) {
407
            apr_shm_remove(fname, gpool);
395
            apr_shm_remove(fname, pool);
408
            rv = apr_shm_create(&shm, size, fname, gpool);
396
            rv = apr_shm_create(&shm, size, fname, gpool);
409
        }
397
        }
410
        else {
398
        else {
411
            rv = apr_shm_create(&shm, size, NULL, gpool);
399
            rv = apr_shm_create(&shm, size, NULL, pool);
412
        }
400
        }
413
        ap_log_error(APLOG_MARK, rv == APR_SUCCESS ? APLOG_DEBUG : APLOG_ERR,
401
        ap_log_error(APLOG_MARK, rv == APR_SUCCESS ? APLOG_DEBUG : APLOG_ERR,
414
                     rv, ap_server_conf, APLOGNO(02611)
402
                     rv, ap_server_conf, APLOGNO(02611)
Lines 418-472 static apr_status_t slotmem_create(ap_slotmem_inst Link Here
418
        if (rv != APR_SUCCESS) {
406
        if (rv != APR_SUCCESS) {
419
            return rv;
407
            return rv;
420
        }
408
        }
421
        ptr = (char *)apr_shm_baseaddr_get(shm);
409
422
        desc.size = item_size;
410
        desc = (sharedslotdesc_t *)apr_shm_baseaddr_get(shm);
423
        desc.num = item_num;
411
        memset(desc, 0, size);
424
        desc.type = type;
412
        desc->size = item_size;
425
        memcpy(ptr, &desc, sizeof(desc));
413
        desc->num = item_num;
426
        ptr += AP_SLOTMEM_OFFSET;
414
        desc->type = type;
427
        memset(ptr, 0, dsize);
415
428
        /*
416
        /*
429
         * TODO: Error check the below... What error makes
417
         * TODO: Error check the below... What error makes
430
         * sense if the restore fails? Any?
418
         * sense if the restore fails? Any?
419
         * For now, we continue with a fresh new slotmem,
420
         * but NOTICE in the log.
431
         */
421
         */
432
        if (persist) {
422
        if (persist) {
433
            rv = restore_slotmem(ptr, pname, dsize, pool);
423
            rv = restore_slotmem(desc, pname, size, pool);
434
            if (rv == APR_SUCCESS) {
424
            if (rv == APR_SUCCESS) {
435
                restored = 1;
425
                restored = 1;
436
            }
426
            }
437
            else {
427
            else {
438
                /* just in case, re-zero */
428
                /* just in case, re-zero */
439
                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
429
                ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
440
                             APLOGNO(02554) "could not restore %s", fname);
430
                             APLOGNO(02554) "could not restore %s", fname);
441
                memset(ptr, 0, dsize);
431
                memset((char *)desc + AP_SLOTMEM_OFFSET, 0,
432
                       size - AP_SLOTMEM_OFFSET);
442
            }
433
            }
443
        }
434
        }
444
    }
435
    }
445
436
437
    p = fbased ? gpool : pool;
438
    ptr = (char *)desc + AP_SLOTMEM_OFFSET;
439
446
    /* For the chained slotmem stuff */
440
    /* For the chained slotmem stuff */
447
    res = (ap_slotmem_instance_t *) apr_pcalloc(gpool,
441
    res = apr_pcalloc(p, sizeof(ap_slotmem_instance_t));
448
                                                sizeof(ap_slotmem_instance_t));
442
    res->name = apr_pstrdup(p, fname);
449
    res->name = apr_pstrdup(gpool, fname);
443
    res->pname = apr_pstrdup(p, pname);
450
    res->pname = apr_pstrdup(gpool, pname);
451
    res->fbased = fbased;
444
    res->fbased = fbased;
452
    res->shm = shm;
445
    res->shm = shm;
446
    res->persist = (void *)ptr;
453
    res->num_free = (unsigned int *)ptr;
447
    res->num_free = (unsigned int *)ptr;
448
    ptr += AP_UNSIGNEDINT_OFFSET;
454
    if (!restored) {
449
    if (!restored) {
455
        *res->num_free = item_num;
450
        *res->num_free = item_num;
456
    }
451
    }
457
    res->persist = (void *)ptr;
458
    ptr += AP_UNSIGNEDINT_OFFSET;
459
    res->base = (void *)ptr;
452
    res->base = (void *)ptr;
460
    res->desc = desc;
453
    res->desc = desc;
461
    res->gpool = gpool;
454
    res->pool = pool;
462
    res->next = NULL;
455
    res->next = NULL;
463
    res->inuse = ptr + basesize;
456
    res->inuse = ptr + basesize;
464
    if (globallistmem == NULL) {
457
    if (fbased) {
465
        globallistmem = res;
458
        if (globallistmem == NULL) {
459
            globallistmem = res;
460
        }
461
        else {
462
            next->next = res;
463
        }
466
    }
464
    }
467
    else {
468
        next->next = res;
469
    }
470
465
471
    *new = res;
466
    *new = res;
472
    return APR_SUCCESS;
467
    return APR_SUCCESS;
Lines 480-493 static apr_status_t slotmem_attach(ap_slotmem_inst Link Here
480
    char *ptr;
475
    char *ptr;
481
    ap_slotmem_instance_t *res;
476
    ap_slotmem_instance_t *res;
482
    ap_slotmem_instance_t *next = globallistmem;
477
    ap_slotmem_instance_t *next = globallistmem;
483
    sharedslotdesc_t desc;
478
    sharedslotdesc_t *desc;
484
    const char *fname;
479
    const char *fname;
485
    apr_shm_t *shm;
480
    apr_shm_t *shm;
486
    apr_status_t rv;
481
    apr_status_t rv;
487
482
488
    if (gpool == NULL) {
489
        return APR_ENOSHMAVAIL;
490
    }
491
    if (!slotmem_filenames(pool, name, &fname, NULL)) {
483
    if (!slotmem_filenames(pool, name, &fname, NULL)) {
492
        return APR_ENOSHMAVAIL;
484
        return APR_ENOSHMAVAIL;
493
    }
485
    }
Lines 501-508 static apr_status_t slotmem_attach(ap_slotmem_inst Link Here
501
            if (strcmp(next->name, fname) == 0) {
493
            if (strcmp(next->name, fname) == 0) {
502
                /* we already have it */
494
                /* we already have it */
503
                *new = next;
495
                *new = next;
504
                *item_size = next->desc.size;
496
                *item_size = next->desc->size;
505
                *item_num = next->desc.num;
497
                *item_num = next->desc->num;
506
                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
498
                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
507
                             APLOGNO(02302)
499
                             APLOGNO(02302)
508
                             "attach found %s: %"APR_SIZE_T_FMT"/%u", fname,
500
                             "attach found %s: %"APR_SIZE_T_FMT"/%u", fname,
Lines 523-545 static apr_status_t slotmem_attach(ap_slotmem_inst Link Here
523
    }
515
    }
524
516
525
    /* Read the description of the slotmem */
517
    /* Read the description of the slotmem */
526
    ptr = (char *)apr_shm_baseaddr_get(shm);
518
    desc = (sharedslotdesc_t *)apr_shm_baseaddr_get(shm);
527
    memcpy(&desc, ptr, sizeof(desc));
519
    ptr = (char *)desc + AP_SLOTMEM_OFFSET;
528
    ptr += AP_SLOTMEM_OFFSET;
529
520
530
    /* For the chained slotmem stuff */
521
    /* For the chained slotmem stuff */
531
    res = (ap_slotmem_instance_t *) apr_pcalloc(gpool,
522
    res = apr_pcalloc(gpool, sizeof(ap_slotmem_instance_t));
532
                                                sizeof(ap_slotmem_instance_t));
533
    res->name = apr_pstrdup(gpool, fname);
523
    res->name = apr_pstrdup(gpool, fname);
534
    res->fbased = 1;
524
    res->fbased = 1;
535
    res->shm = shm;
525
    res->shm = shm;
526
    res->persist = (void *)ptr;
536
    res->num_free = (unsigned int *)ptr;
527
    res->num_free = (unsigned int *)ptr;
537
    res->persist = (void *)ptr;
538
    ptr += AP_UNSIGNEDINT_OFFSET;
528
    ptr += AP_UNSIGNEDINT_OFFSET;
539
    res->base = (void *)ptr;
529
    res->base = (void *)ptr;
540
    res->desc = desc;
530
    res->desc = desc;
541
    res->gpool = gpool;
531
    res->pool = pool;
542
    res->inuse = ptr + (desc.size * desc.num);
532
    res->inuse = ptr + (desc->size * desc->num);
543
    res->next = NULL;
533
    res->next = NULL;
544
    if (globallistmem == NULL) {
534
    if (globallistmem == NULL) {
545
        globallistmem = res;
535
        globallistmem = res;
Lines 549-556 static apr_status_t slotmem_attach(ap_slotmem_inst Link Here
549
    }
539
    }
550
540
551
    *new = res;
541
    *new = res;
552
    *item_size = desc.size;
542
    *item_size = desc->size;
553
    *item_num = desc.num;
543
    *item_num = desc->num;
554
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
544
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
555
                 APLOGNO(02303)
545
                 APLOGNO(02303)
556
                 "attach found %s: %"APR_SIZE_T_FMT"/%u", fname,
546
                 "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) {
556
    if (!slot) {
567
        return APR_ENOSHMAVAIL;
557
        return APR_ENOSHMAVAIL;
568
    }
558
    }
569
    if (id >= slot->desc.num) {
559
    if (id >= slot->desc->num) {
570
        return APR_EINVAL;
560
        return APR_EINVAL;
571
    }
561
    }
572
562
573
    ptr = (char *)slot->base + slot->desc.size * id;
563
    ptr = (char *)slot->base + slot->desc->size * id;
574
    if (!ptr) {
564
    if (!ptr) {
575
        return APR_ENOSHMAVAIL;
565
        return APR_ENOSHMAVAIL;
576
    }
566
    }
Lines 590-596 static apr_status_t slotmem_get(ap_slotmem_instanc Link Here
590
    }
580
    }
591
581
592
    inuse = slot->inuse + id;
582
    inuse = slot->inuse + id;
593
    if (id >= slot->desc.num) {
583
    if (id >= slot->desc->num) {
594
        return APR_EINVAL;
584
        return APR_EINVAL;
595
    }
585
    }
596
    if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) {
586
    if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) {
Lines 617-623 static apr_status_t slotmem_put(ap_slotmem_instanc Link Here
617
    }
607
    }
618
608
619
    inuse = slot->inuse + id;
609
    inuse = slot->inuse + id;
620
    if (id >= slot->desc.num) {
610
    if (id >= slot->desc->num) {
621
        return APR_EINVAL;
611
        return APR_EINVAL;
622
    }
612
    }
623
    if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) {
613
    if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) {
Lines 634-640 static apr_status_t slotmem_put(ap_slotmem_instanc Link Here
634
624
635
static unsigned int slotmem_num_slots(ap_slotmem_instance_t *slot)
625
static unsigned int slotmem_num_slots(ap_slotmem_instance_t *slot)
636
{
626
{
637
    return slot->desc.num;
627
    return slot->desc->num;
638
}
628
}
639
629
640
static unsigned int slotmem_num_free_slots(ap_slotmem_instance_t *slot)
630
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 {
634
    else {
645
        unsigned int i, counter=0;
635
        unsigned int i, counter=0;
646
        char *inuse = slot->inuse;
636
        char *inuse = slot->inuse;
647
        for (i=0; i<slot->desc.num; i++, inuse++) {
637
        for (i=0; i<slot->desc->num; i++, inuse++) {
648
            if (!*inuse)
638
            if (!*inuse)
649
                counter++;
639
                counter++;
650
        }
640
        }
Lines 654-660 static unsigned int slotmem_num_free_slots(ap_slot Link Here
654
644
655
static apr_size_t slotmem_slot_size(ap_slotmem_instance_t *slot)
645
static apr_size_t slotmem_slot_size(ap_slotmem_instance_t *slot)
656
{
646
{
657
    return slot->desc.size;
647
    return slot->desc->size;
658
}
648
}
659
649
660
static apr_status_t slotmem_grab(ap_slotmem_instance_t *slot, unsigned int *id)
650
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
658
669
    inuse = slot->inuse;
659
    inuse = slot->inuse;
670
660
671
    for (i = 0; i < slot->desc.num; i++, inuse++) {
661
    for (i = 0; i < slot->desc->num; i++, inuse++) {
672
        if (!*inuse) {
662
        if (!*inuse) {
673
            break;
663
            break;
674
        }
664
        }
675
    }
665
    }
676
    if (i >= slot->desc.num) {
666
    if (i >= slot->desc->num) {
677
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02293)
667
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02293)
678
                     "slotmem(%s) grab failed. Num %u/num_free %u",
668
                     "slotmem(%s) grab failed. Num %u/num_free %u",
679
                     slot->name, slotmem_num_slots(slot),
669
                     slot->name, slotmem_num_slots(slot),
Lines 694-700 static apr_status_t slotmem_fgrab(ap_slotmem_insta Link Here
694
        return APR_ENOSHMAVAIL;
684
        return APR_ENOSHMAVAIL;
695
    }
685
    }
696
686
697
    if (id >= slot->desc.num) {
687
    if (id >= slot->desc->num) {
698
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02397)
688
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02397)
699
                     "slotmem(%s) fgrab failed. Num %u/num_free %u",
689
                     "slotmem(%s) fgrab failed. Num %u/num_free %u",
700
                     slot->name, slotmem_num_slots(slot),
690
                     slot->name, slotmem_num_slots(slot),
Lines 721-732 static apr_status_t slotmem_release(ap_slotmem_ins Link Here
721
711
722
    inuse = slot->inuse;
712
    inuse = slot->inuse;
723
713
724
    if (id >= slot->desc.num || !inuse[id] ) {
714
    if (id >= slot->desc->num || !inuse[id] ) {
725
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02294)
715
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02294)
726
                     "slotmem(%s) release failed. Num %u/inuse[%u] %d",
716
                     "slotmem(%s) release failed. Num %u/inuse[%u] %d",
727
                     slot->name, slotmem_num_slots(slot),
717
                     slot->name, slotmem_num_slots(slot),
728
                     id, (int)inuse[id]);
718
                     id, (int)inuse[id]);
729
        if (id >= slot->desc.num) {
719
        if (id >= slot->desc->num) {
730
            return APR_EINVAL;
720
            return APR_EINVAL;
731
        } else {
721
        } else {
732
            return APR_NOTFOUND;
722
            return APR_NOTFOUND;
Lines 759-800 static const ap_slotmem_provider_t *slotmem_shm_ge Link Here
759
    return (&storage);
749
    return (&storage);
760
}
750
}
761
751
762
/* initialise the global pool */
752
/* Initialize or reuse the retained slotmems list, and register the
763
static void slotmem_shm_initgpool(apr_pool_t *p)
753
 * cleanup to make sure the persisted SHMs are stored and the retained
754
 * data are up to date on next restart/stop.
755
 */
756
static int pre_config(apr_pool_t *p, apr_pool_t *plog,
757
                      apr_pool_t *ptemp)
764
{
758
{
765
    gpool = p;
759
    void *is_startup = NULL;
766
}
760
    const char *retained_key = "mod_slotmem_shm";
767
761
768
/* Add the pool_clean routine */
762
    retained_globallistmem = ap_retained_data_get(retained_key);
769
static void slotmem_shm_initialize_cleanup(apr_pool_t *p)
763
    if (!retained_globallistmem) {
770
{
764
        retained_globallistmem =
771
    apr_pool_cleanup_register(p, &globallistmem, cleanup_slotmem,
765
            ap_retained_data_create(retained_key,
766
                                    sizeof *retained_globallistmem);
767
    }
768
    globallistmem = *retained_globallistmem;
769
770
    if (ap_state_query(AP_SQ_MAIN_STATE) != AP_SQ_MS_CREATE_PRE_CONFIG) {
771
        gpool = ap_pglobal;
772
    }
773
    else {
774
        is_startup = (void *)1;
775
        gpool = p;
776
    }
777
778
    apr_pool_cleanup_register(p, is_startup, cleanup_slotmem,
772
                              apr_pool_cleanup_null);
779
                              apr_pool_cleanup_null);
773
}
774
780
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;
781
    return OK;
783
}
782
}
784
783
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)
784
static void ap_slotmem_shm_register_hook(apr_pool_t *p)
793
{
785
{
794
    const ap_slotmem_provider_t *storage = slotmem_shm_getstorage();
786
    const ap_slotmem_provider_t *storage = slotmem_shm_getstorage();
795
    ap_register_provider(p, AP_SLOTMEM_PROVIDER_GROUP, "shm",
787
    ap_register_provider(p, AP_SLOTMEM_PROVIDER_GROUP, "shm",
796
                         AP_SLOTMEM_PROVIDER_VERSION, storage);
788
                         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);
789
    ap_hook_pre_config(pre_config, NULL, NULL, APR_HOOK_MIDDLE);
799
}
790
}
800
791

Return to bug 62044