/src/httpd/server/util_mutex.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Licensed to the Apache Software Foundation (ASF) under one or more |
2 | | * contributor license agreements. See the NOTICE file distributed with |
3 | | * this work for additional information regarding copyright ownership. |
4 | | * The ASF licenses this file to You under the Apache License, Version 2.0 |
5 | | * (the "License"); you may not use this file except in compliance with |
6 | | * the License. You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | /* |
18 | | * util_mutex.c: Useful functions for determining allowable |
19 | | * mutexes and mutex settings |
20 | | */ |
21 | | |
22 | | |
23 | | #include "apr.h" |
24 | | #include "apr_hash.h" |
25 | | #include "apr_strings.h" |
26 | | #include "apr_lib.h" |
27 | | |
28 | | #define APR_WANT_STRFUNC |
29 | | #include "apr_want.h" |
30 | | |
31 | | #include "ap_config.h" |
32 | | #include "httpd.h" |
33 | | #include "http_main.h" |
34 | | #include "http_config.h" |
35 | | #include "http_core.h" |
36 | | #include "http_log.h" |
37 | | #include "util_mutex.h" |
38 | | #if AP_NEED_SET_MUTEX_PERMS |
39 | | #include "unixd.h" |
40 | | #endif |
41 | | #ifdef HAVE_UNISTD_H |
42 | | #include <unistd.h> /* getpid() */ |
43 | | #endif |
44 | | |
45 | | /* we know core's module_index is 0 */ |
46 | | #undef APLOG_MODULE_INDEX |
47 | | #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX |
48 | | |
49 | | AP_DECLARE(apr_status_t) ap_parse_mutex(const char *arg, apr_pool_t *pool, |
50 | | apr_lockmech_e *mutexmech, |
51 | | const char **mutexfile) |
52 | 0 | { |
53 | | /* Split arg into meth and file */ |
54 | 0 | char *meth = apr_pstrdup(pool, arg); |
55 | 0 | char *file = strchr(meth, ':'); |
56 | 0 | if (file) { |
57 | 0 | *(file++) = '\0'; |
58 | 0 | if (!*file) { |
59 | 0 | file = NULL; |
60 | 0 | } |
61 | 0 | } |
62 | | |
63 | | /* APR determines temporary filename unless overridden below, |
64 | | * we presume file indicates an mutexfile is a file path |
65 | | * unless the method sets mutexfile=file and NULLs file |
66 | | */ |
67 | 0 | *mutexfile = NULL; |
68 | |
|
69 | 0 | if (!strcasecmp(meth, "none") || !strcasecmp(meth, "no")) { |
70 | 0 | return APR_ENOLOCK; |
71 | 0 | } |
72 | | |
73 | | /* NOTE: previously, 'yes' implied 'sem' */ |
74 | 0 | if (!strcasecmp(meth, "default") || !strcasecmp(meth, "yes")) { |
75 | 0 | *mutexmech = APR_LOCK_DEFAULT; |
76 | 0 | } |
77 | 0 | #if APR_HAS_FCNTL_SERIALIZE |
78 | 0 | else if (!strcasecmp(meth, "fcntl") || !strcasecmp(meth, "file")) { |
79 | 0 | *mutexmech = APR_LOCK_FCNTL; |
80 | 0 | } |
81 | 0 | #endif |
82 | 0 | #if APR_HAS_FLOCK_SERIALIZE |
83 | 0 | else if (!strcasecmp(meth, "flock") || !strcasecmp(meth, "file")) { |
84 | 0 | *mutexmech = APR_LOCK_FLOCK; |
85 | 0 | } |
86 | 0 | #endif |
87 | 0 | #if APR_HAS_POSIXSEM_SERIALIZE |
88 | 0 | else if (!strcasecmp(meth, "posixsem") || !strcasecmp(meth, "sem")) { |
89 | 0 | *mutexmech = APR_LOCK_POSIXSEM; |
90 | | /* Posix/SysV semaphores aren't file based, use the literal name |
91 | | * if provided and fall back on APR's default if not. Today, APR |
92 | | * will ignore it, but once supported it has an absurdly short limit. |
93 | | */ |
94 | 0 | if (file) { |
95 | 0 | *mutexfile = apr_pstrdup(pool, file); |
96 | |
|
97 | 0 | file = NULL; |
98 | 0 | } |
99 | 0 | } |
100 | 0 | #endif |
101 | 0 | #if APR_HAS_SYSVSEM_SERIALIZE |
102 | 0 | else if (!strcasecmp(meth, "sysvsem") || !strcasecmp(meth, "sem")) { |
103 | 0 | *mutexmech = APR_LOCK_SYSVSEM; |
104 | 0 | } |
105 | 0 | #endif |
106 | 0 | #if APR_HAS_PROC_PTHREAD_SERIALIZE |
107 | 0 | else if (!strcasecmp(meth, "pthread")) { |
108 | 0 | *mutexmech = APR_LOCK_PROC_PTHREAD; |
109 | 0 | } |
110 | 0 | #endif |
111 | 0 | else { |
112 | 0 | return APR_ENOTIMPL; |
113 | 0 | } |
114 | | |
115 | | /* Unless the method above assumed responsibility for setting up |
116 | | * mutexfile and NULLing out file, presume it is a file we |
117 | | * are looking to use |
118 | | */ |
119 | 0 | if (file) { |
120 | 0 | *mutexfile = ap_runtime_dir_relative(pool, file); |
121 | 0 | if (!*mutexfile) { |
122 | 0 | return APR_BADARG; |
123 | 0 | } |
124 | 0 | } |
125 | | |
126 | 0 | return APR_SUCCESS; |
127 | 0 | } |
128 | | |
129 | | typedef struct { |
130 | | apr_int32_t options; |
131 | | unsigned int set : 1; |
132 | | unsigned int none : 1; |
133 | | unsigned int omit_pid : 1; |
134 | | apr_lockmech_e mech; |
135 | | const char *dir; |
136 | | } mutex_cfg_t; |
137 | | |
138 | | /* hash is created the first time a module calls ap_mutex_register(), |
139 | | * rather than attempting to be the REALLY_REALLY_FIRST pre-config |
140 | | * hook; it is cleaned up when the associated pool goes away; assume |
141 | | * pconf is the pool passed to ap_mutex_register() |
142 | | */ |
143 | | static apr_hash_t *mxcfg_by_type; |
144 | | |
145 | | AP_DECLARE_NONSTD(void) ap_mutex_init(apr_pool_t *p) |
146 | 0 | { |
147 | 0 | mutex_cfg_t *def; |
148 | |
|
149 | 0 | if (mxcfg_by_type) { |
150 | 0 | return; |
151 | 0 | } |
152 | | |
153 | 0 | mxcfg_by_type = apr_hash_make(p); |
154 | 0 | apr_pool_cleanup_register(p, &mxcfg_by_type, ap_pool_cleanup_set_null, |
155 | 0 | apr_pool_cleanup_null); |
156 | | |
157 | | /* initialize default mutex configuration */ |
158 | 0 | def = apr_pcalloc(p, sizeof *def); |
159 | 0 | def->mech = APR_LOCK_DEFAULT; |
160 | 0 | def->dir = ap_runtime_dir_relative(p, ""); |
161 | 0 | apr_hash_set(mxcfg_by_type, "default", APR_HASH_KEY_STRING, def); |
162 | 0 | } |
163 | | |
164 | | AP_DECLARE_NONSTD(const char *)ap_set_mutex(cmd_parms *cmd, void *dummy, |
165 | | const char *arg) |
166 | 0 | { |
167 | 0 | apr_pool_t *p = cmd->pool; |
168 | 0 | apr_pool_t *ptemp = cmd->temp_pool; |
169 | 0 | const char **elt; |
170 | 0 | const char *mechdir; |
171 | 0 | int no_mutex = 0, omit_pid = 0; |
172 | 0 | apr_array_header_t *type_list; |
173 | 0 | apr_lockmech_e mech; |
174 | 0 | apr_status_t rv; |
175 | 0 | const char *mutexdir; |
176 | 0 | mutex_cfg_t *mxcfg; |
177 | 0 | const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); |
178 | |
|
179 | 0 | if (err != NULL) { |
180 | 0 | return err; |
181 | 0 | } |
182 | | |
183 | 0 | mechdir = ap_getword_conf(cmd->pool, &arg); |
184 | 0 | if (*mechdir == '\0') { |
185 | 0 | return "Mutex requires at least a mechanism argument (" |
186 | 0 | AP_ALL_AVAILABLE_MUTEXES_STRING ")"; |
187 | 0 | } |
188 | | |
189 | 0 | rv = ap_parse_mutex(mechdir, p, &mech, &mutexdir); |
190 | 0 | if (rv == APR_ENOTIMPL) { |
191 | 0 | return apr_pstrcat(p, "Invalid Mutex argument ", mechdir, |
192 | 0 | " (" AP_ALL_AVAILABLE_MUTEXES_STRING ")", NULL); |
193 | 0 | } |
194 | 0 | else if (rv == APR_BADARG |
195 | 0 | || (mutexdir && !ap_is_directory(ptemp, mutexdir))) { |
196 | 0 | return apr_pstrcat(p, "Invalid Mutex directory in argument ", |
197 | 0 | mechdir, NULL); |
198 | 0 | } |
199 | 0 | else if (rv == APR_ENOLOCK) { /* "none" */ |
200 | 0 | no_mutex = 1; |
201 | 0 | } |
202 | | |
203 | | /* "OmitPID" can appear at the end of the list, so build a list of |
204 | | * mutex type names while looking for "OmitPID" (anywhere) or the end |
205 | | */ |
206 | 0 | type_list = apr_array_make(cmd->pool, 4, sizeof(const char *)); |
207 | 0 | while (*arg) { |
208 | 0 | const char *s = ap_getword_conf(cmd->pool, &arg); |
209 | |
|
210 | 0 | if (!strcasecmp(s, "omitpid")) { |
211 | 0 | omit_pid = 1; |
212 | 0 | } |
213 | 0 | else { |
214 | 0 | const char **new_type = (const char **)apr_array_push(type_list); |
215 | 0 | *new_type = s; |
216 | 0 | } |
217 | 0 | } |
218 | |
|
219 | 0 | if (apr_is_empty_array(type_list)) { /* no mutex type? assume "default" */ |
220 | 0 | const char **new_type = (const char **)apr_array_push(type_list); |
221 | 0 | *new_type = "default"; |
222 | 0 | } |
223 | |
|
224 | 0 | while ((elt = (const char **)apr_array_pop(type_list)) != NULL) { |
225 | 0 | const char *type = *elt; |
226 | 0 | mxcfg = apr_hash_get(mxcfg_by_type, type, APR_HASH_KEY_STRING); |
227 | 0 | if (!mxcfg) { |
228 | 0 | return apr_psprintf(p, "Mutex type %s is not valid", type); |
229 | 0 | } |
230 | | |
231 | 0 | mxcfg->none = 0; /* in case that was the default */ |
232 | 0 | mxcfg->omit_pid = omit_pid; |
233 | |
|
234 | 0 | mxcfg->set = 1; |
235 | 0 | if (no_mutex) { |
236 | 0 | if (!(mxcfg->options & AP_MUTEX_ALLOW_NONE)) { |
237 | 0 | return apr_psprintf(p, |
238 | 0 | "None is not allowed for mutex type %s", |
239 | 0 | type); |
240 | 0 | } |
241 | 0 | mxcfg->none = 1; |
242 | 0 | } |
243 | 0 | else { |
244 | 0 | mxcfg->mech = mech; |
245 | 0 | if (mutexdir) { /* retain mutex default if not configured */ |
246 | 0 | mxcfg->dir = mutexdir; |
247 | 0 | } |
248 | 0 | } |
249 | 0 | } |
250 | | |
251 | 0 | return NULL; |
252 | 0 | } |
253 | | |
254 | | AP_DECLARE(apr_status_t) ap_mutex_register(apr_pool_t *pconf, |
255 | | const char *type, |
256 | | const char *default_dir, |
257 | | apr_lockmech_e default_mech, |
258 | | apr_int32_t options) |
259 | 0 | { |
260 | 0 | mutex_cfg_t *mxcfg = apr_pcalloc(pconf, sizeof *mxcfg); |
261 | |
|
262 | 0 | if ((options & ~(AP_MUTEX_ALLOW_NONE | AP_MUTEX_DEFAULT_NONE))) { |
263 | 0 | return APR_EINVAL; |
264 | 0 | } |
265 | | |
266 | 0 | ap_mutex_init(pconf); /* in case this mod's pre-config ran before core's */ |
267 | |
|
268 | 0 | mxcfg->options = options; |
269 | 0 | if (options & AP_MUTEX_DEFAULT_NONE) { |
270 | 0 | mxcfg->none = 1; |
271 | 0 | } |
272 | 0 | mxcfg->dir = default_dir; /* usually NULL */ |
273 | 0 | mxcfg->mech = default_mech; /* usually APR_LOCK_DEFAULT */ |
274 | 0 | apr_hash_set(mxcfg_by_type, type, APR_HASH_KEY_STRING, mxcfg); |
275 | |
|
276 | 0 | return APR_SUCCESS; |
277 | 0 | } |
278 | | |
279 | | static int mutex_needs_file(apr_lockmech_e mech) |
280 | 0 | { |
281 | 0 | if (mech != APR_LOCK_FLOCK |
282 | 0 | && mech != APR_LOCK_FCNTL |
283 | | #if APR_USE_FLOCK_SERIALIZE || APR_USE_FCNTL_SERIALIZE |
284 | | && mech != APR_LOCK_DEFAULT |
285 | | #endif |
286 | 0 | ) { |
287 | 0 | return 0; |
288 | 0 | } |
289 | 0 | return 1; |
290 | 0 | } |
291 | | |
292 | | static const char *get_mutex_filename(apr_pool_t *p, mutex_cfg_t *mxcfg, |
293 | | const char *type, |
294 | | const char *instance_id) |
295 | 0 | { |
296 | 0 | const char *pid_suffix = ""; |
297 | |
|
298 | 0 | if (!mutex_needs_file(mxcfg->mech)) { |
299 | 0 | return NULL; |
300 | 0 | } |
301 | | |
302 | 0 | #if HAVE_UNISTD_H |
303 | 0 | if (!mxcfg->omit_pid) { |
304 | 0 | pid_suffix = apr_psprintf(p, ".%" APR_PID_T_FMT, getpid()); |
305 | 0 | } |
306 | 0 | #endif |
307 | |
|
308 | 0 | return ap_runtime_dir_relative(p, |
309 | 0 | apr_pstrcat(p, |
310 | 0 | mxcfg->dir, |
311 | 0 | "/", |
312 | 0 | type, |
313 | 0 | instance_id ? "-" : "", |
314 | 0 | instance_id ? instance_id : "", |
315 | 0 | pid_suffix, |
316 | 0 | NULL)); |
317 | 0 | } |
318 | | |
319 | | static mutex_cfg_t *mxcfg_lookup(apr_pool_t *p, const char *type) |
320 | 0 | { |
321 | 0 | mutex_cfg_t *defcfg, *mxcfg, *newcfg; |
322 | |
|
323 | 0 | defcfg = apr_hash_get(mxcfg_by_type, "default", APR_HASH_KEY_STRING); |
324 | | |
325 | | /* MUST exist in table, or wasn't registered */ |
326 | 0 | mxcfg = apr_hash_get(mxcfg_by_type, type, APR_HASH_KEY_STRING); |
327 | 0 | if (!mxcfg) { |
328 | 0 | return NULL; |
329 | 0 | } |
330 | | |
331 | | /* order of precedence: |
332 | | * 1. Mutex directive for this mutex |
333 | | * 2. Mutex directive for "default" |
334 | | * 3. Defaults for this mutex from ap_mutex_register() |
335 | | * 4. Global defaults |
336 | | */ |
337 | | |
338 | 0 | if (mxcfg->set) { |
339 | 0 | newcfg = mxcfg; |
340 | 0 | } |
341 | 0 | else if (defcfg->set) { |
342 | 0 | newcfg = defcfg; |
343 | 0 | } |
344 | 0 | else if (mxcfg->none || mxcfg->mech != APR_LOCK_DEFAULT) { |
345 | 0 | newcfg = mxcfg; |
346 | 0 | } |
347 | 0 | else { |
348 | 0 | newcfg = defcfg; |
349 | 0 | } |
350 | |
|
351 | 0 | if (!newcfg->none && mutex_needs_file(newcfg->mech) && !newcfg->dir) { |
352 | | /* a file-based mutex mechanism was configured, but |
353 | | * without a mutex file directory; go back through |
354 | | * the chain to find the directory, store in new |
355 | | * mutex cfg structure |
356 | | */ |
357 | 0 | newcfg = apr_pmemdup(p, newcfg, sizeof *newcfg); |
358 | | |
359 | | /* !true if dir not already set: mxcfg->set && defcfg->dir */ |
360 | 0 | if (defcfg->set && defcfg->dir) { |
361 | 0 | newcfg->dir = defcfg->dir; |
362 | 0 | } |
363 | 0 | else if (mxcfg->dir) { |
364 | 0 | newcfg->dir = mxcfg->dir; |
365 | 0 | } |
366 | 0 | else { |
367 | 0 | newcfg->dir = defcfg->dir; |
368 | 0 | } |
369 | 0 | } |
370 | |
|
371 | 0 | return newcfg; |
372 | 0 | } |
373 | | |
374 | | static void log_bad_create_options(server_rec *s, const char *type) |
375 | 0 | { |
376 | 0 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(00021) |
377 | 0 | "Invalid options were specified when creating the %s mutex", |
378 | 0 | type); |
379 | 0 | } |
380 | | |
381 | | static void log_unknown_type(server_rec *s, const char *type) |
382 | 0 | { |
383 | 0 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(00022) |
384 | 0 | "Can't create mutex of unknown type %s", type); |
385 | 0 | } |
386 | | |
387 | | static void log_create_failure(apr_status_t rv, server_rec *s, const char *type, |
388 | | const char *fname) |
389 | 0 | { |
390 | 0 | ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(00023) |
391 | 0 | "Couldn't create the %s mutex %s%s%s", type, |
392 | 0 | fname ? "(file " : "", |
393 | 0 | fname ? fname : "", |
394 | 0 | fname ? ")" : ""); |
395 | 0 | } |
396 | | |
397 | | #ifdef AP_NEED_SET_MUTEX_PERMS |
398 | | static void log_perms_failure(apr_status_t rv, server_rec *s, const char *type) |
399 | 0 | { |
400 | 0 | ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(00024) |
401 | 0 | "Couldn't set permissions on the %s mutex; " |
402 | 0 | "check User and Group directives", |
403 | 0 | type); |
404 | 0 | } |
405 | | #endif |
406 | | |
407 | | AP_DECLARE(apr_status_t) ap_global_mutex_create(apr_global_mutex_t **mutex, |
408 | | const char **name, |
409 | | const char *type, |
410 | | const char *instance_id, |
411 | | server_rec *s, apr_pool_t *p, |
412 | | apr_int32_t options) |
413 | 0 | { |
414 | 0 | apr_status_t rv; |
415 | 0 | const char *fname; |
416 | 0 | mutex_cfg_t *mxcfg = mxcfg_lookup(p, type); |
417 | |
|
418 | 0 | if (options) { |
419 | 0 | log_bad_create_options(s, type); |
420 | 0 | return APR_EINVAL; |
421 | 0 | } |
422 | | |
423 | 0 | if (!mxcfg) { |
424 | 0 | log_unknown_type(s, type); |
425 | 0 | return APR_EINVAL; |
426 | 0 | } |
427 | | |
428 | 0 | if (mxcfg->none) { |
429 | 0 | *mutex = NULL; |
430 | 0 | return APR_SUCCESS; |
431 | 0 | } |
432 | | |
433 | 0 | fname = get_mutex_filename(p, mxcfg, type, instance_id); |
434 | |
|
435 | 0 | rv = apr_global_mutex_create(mutex, fname, mxcfg->mech, p); |
436 | 0 | if (rv != APR_SUCCESS) { |
437 | 0 | log_create_failure(rv, s, type, fname); |
438 | 0 | return rv; |
439 | 0 | } |
440 | | |
441 | 0 | if (name) |
442 | 0 | *name = fname; |
443 | |
|
444 | 0 | #ifdef AP_NEED_SET_MUTEX_PERMS |
445 | 0 | rv = ap_unixd_set_global_mutex_perms(*mutex); |
446 | 0 | if (rv != APR_SUCCESS) { |
447 | 0 | log_perms_failure(rv, s, type); |
448 | 0 | } |
449 | 0 | #endif |
450 | |
|
451 | 0 | return rv; |
452 | 0 | } |
453 | | |
454 | | AP_DECLARE(apr_status_t) ap_proc_mutex_create(apr_proc_mutex_t **mutex, |
455 | | const char **name, |
456 | | const char *type, |
457 | | const char *instance_id, |
458 | | server_rec *s, apr_pool_t *p, |
459 | | apr_int32_t options) |
460 | 0 | { |
461 | 0 | apr_status_t rv; |
462 | 0 | const char *fname; |
463 | 0 | mutex_cfg_t *mxcfg = mxcfg_lookup(p, type); |
464 | |
|
465 | 0 | if (options) { |
466 | 0 | log_bad_create_options(s, type); |
467 | 0 | return APR_EINVAL; |
468 | 0 | } |
469 | | |
470 | 0 | if (!mxcfg) { |
471 | 0 | log_unknown_type(s, type); |
472 | 0 | return APR_EINVAL; |
473 | 0 | } |
474 | | |
475 | 0 | if (mxcfg->none) { |
476 | 0 | *mutex = NULL; |
477 | 0 | return APR_SUCCESS; |
478 | 0 | } |
479 | | |
480 | 0 | fname = get_mutex_filename(p, mxcfg, type, instance_id); |
481 | |
|
482 | 0 | rv = apr_proc_mutex_create(mutex, fname, mxcfg->mech, p); |
483 | 0 | if (rv != APR_SUCCESS) { |
484 | 0 | log_create_failure(rv, s, type, fname); |
485 | 0 | return rv; |
486 | 0 | } |
487 | | |
488 | 0 | if (name) |
489 | 0 | *name = fname; |
490 | |
|
491 | 0 | #ifdef AP_NEED_SET_MUTEX_PERMS |
492 | 0 | rv = ap_unixd_set_proc_mutex_perms(*mutex); |
493 | 0 | if (rv != APR_SUCCESS) { |
494 | 0 | log_perms_failure(rv, s, type); |
495 | 0 | } |
496 | 0 | #endif |
497 | |
|
498 | 0 | return rv; |
499 | 0 | } |
500 | | |
501 | | AP_CORE_DECLARE(void) ap_dump_mutexes(apr_pool_t *p, server_rec *s, apr_file_t *out) |
502 | 0 | { |
503 | 0 | apr_hash_index_t *idx; |
504 | 0 | mutex_cfg_t *defcfg = apr_hash_get(mxcfg_by_type, "default", APR_HASH_KEY_STRING); |
505 | 0 | for (idx = apr_hash_first(p, mxcfg_by_type); idx; idx = apr_hash_next(idx)) |
506 | 0 | { |
507 | 0 | mutex_cfg_t *mxcfg; |
508 | 0 | const char *name, *mech = "<unknown>"; |
509 | 0 | const void *name_; |
510 | 0 | const char *dir = ""; |
511 | 0 | apr_hash_this(idx, &name_, NULL, NULL); |
512 | 0 | name = name_; |
513 | 0 | mxcfg = mxcfg_lookup(p, name); |
514 | 0 | if (mxcfg == defcfg && strcmp(name, "default") != 0) { |
515 | 0 | apr_file_printf(out, "Mutex %s: using_defaults\n", name); |
516 | 0 | continue; |
517 | 0 | } |
518 | 0 | if (mxcfg->none) { |
519 | 0 | apr_file_printf(out, "Mutex %s: none\n", name); |
520 | 0 | continue; |
521 | 0 | } |
522 | 0 | switch (mxcfg->mech) { |
523 | 0 | case APR_LOCK_DEFAULT: |
524 | 0 | mech = "default"; |
525 | 0 | break; |
526 | 0 | #if APR_HAS_FCNTL_SERIALIZE |
527 | 0 | case APR_LOCK_FCNTL: |
528 | 0 | mech = "fcntl"; |
529 | 0 | break; |
530 | 0 | #endif |
531 | 0 | #if APR_HAS_FLOCK_SERIALIZE |
532 | 0 | case APR_LOCK_FLOCK: |
533 | 0 | mech = "flock"; |
534 | 0 | break; |
535 | 0 | #endif |
536 | 0 | #if APR_HAS_POSIXSEM_SERIALIZE |
537 | 0 | case APR_LOCK_POSIXSEM: |
538 | 0 | mech = "posixsem"; |
539 | 0 | break; |
540 | 0 | #endif |
541 | 0 | #if APR_HAS_SYSVSEM_SERIALIZE |
542 | 0 | case APR_LOCK_SYSVSEM: |
543 | 0 | mech = "sysvsem"; |
544 | 0 | break; |
545 | 0 | #endif |
546 | 0 | #if APR_HAS_PROC_PTHREAD_SERIALIZE |
547 | 0 | case APR_LOCK_PROC_PTHREAD: |
548 | 0 | mech = "pthread"; |
549 | 0 | break; |
550 | 0 | #endif |
551 | 0 | default: |
552 | 0 | ap_assert(0); |
553 | 0 | } |
554 | | |
555 | 0 | if (mxcfg->dir) |
556 | 0 | dir = ap_runtime_dir_relative(p, mxcfg->dir); |
557 | |
|
558 | 0 | apr_file_printf(out, "Mutex %s: dir=\"%s\" mechanism=%s %s\n", name, dir, mech, |
559 | 0 | mxcfg->omit_pid ? "[OmitPid]" : ""); |
560 | 0 | } |
561 | 0 | } |