67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim/* Licensed to the Apache Software Foundation (ASF) under one or more
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * contributor license agreements. See the NOTICE file distributed with
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * this work for additional information regarding copyright ownership.
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * The ASF licenses this file to You under the Apache License, Version 2.0
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * (the "License"); you may not use this file except in compliance with
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * the License. You may obtain a copy of the License at
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * Unless required by applicable law or agreed to in writing, software
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * distributed under the License is distributed on an "AS IS" BASIS,
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * See the License for the specific language governing permissions and
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * limitations under the License.
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * util_mutex.c: Useful functions for determining allowable
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * mutexes and mutex settings
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf/* we know core's module_index is 0 */
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jimAP_DECLARE(apr_status_t) ap_parse_mutex(const char *arg, apr_pool_t *pool,
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim const char **mutexfile)
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim /* Split arg into meth and file */
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim /* APR determines temporary filename unless overridden below,
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * we presume file indicates an mutexfile is a file path
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * unless the method sets mutexfile=file and NULLs file
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick if (!strcasecmp(meth, "none") || !strcasecmp(meth, "no")) {
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim /* NOTE: previously, 'yes' implied 'sem' */
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim if (!strcasecmp(meth, "default") || !strcasecmp(meth, "yes")) {
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim else if (!strcasecmp(meth, "fcntl") || !strcasecmp(meth, "file")) {
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim else if (!strcasecmp(meth, "flock") || !strcasecmp(meth, "file")) {
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim else if (!strcasecmp(meth, "posixsem") || !strcasecmp(meth, "sem")) {
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim /* Posix/SysV semaphores aren't file based, use the literal name
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * if provided and fall back on APR's default if not. Today, APR
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * will ignore it, but once supported it has an absurdly short limit.
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim else if (!strcasecmp(meth, "sysvsem") || !strcasecmp(meth, "sem")) {
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim /* Unless the method above assumed responsibility for setting up
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * mutexfile and NULLing out file, presume it is a file we
67139e2d50d1e11558d87f7042f61cb04bb0d1d2jim * are looking to use
11f2c481e1d57bedb3f758565307501e9a2730ddtrawicktypedef struct {
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick/* hash is created the first time a module calls ap_mutex_register(),
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * rather than attempting to be the REALLY_REALLY_FIRST pre-config
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * hook; it is cleaned up when the associated pool goes away; assume
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * pconf is the pool passed to ap_mutex_register()
f6e47621625cca111811e84e407be84b5b18e9c5sf apr_pool_cleanup_register(p, &mxcfg_by_type, ap_pool_cleanup_set_null,
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick /* initialize default mutex configuration */
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick apr_hash_set(mxcfg_by_type, "default", APR_HASH_KEY_STRING, def);
f4c8f0f5f11dd9f387441204fbe6d109f5c4eb25trawickAP_DECLARE_NONSTD(const char *)ap_set_mutex(cmd_parms *cmd, void *dummy,
2b6c7b8eb5fbc43564898aedac730df7e91da475trawick const char *arg)
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim return "Mutex requires at least a mechanism argument ("
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick return apr_pstrcat(p, "Invalid Mutex argument ", mechdir,
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick return apr_pstrcat(p, "Invalid Mutex directory in argument ",
2b6c7b8eb5fbc43564898aedac730df7e91da475trawick /* "OmitPID" can appear at the end of the list, so build a list of
2b6c7b8eb5fbc43564898aedac730df7e91da475trawick * mutex type names while looking for "OmitPID" (anywhere) or the end
b6b8c27b2adcf08eca23d3b7c2de79880b816a57takashi type_list = apr_array_make(cmd->pool, 4, sizeof(const char *));
b6b8c27b2adcf08eca23d3b7c2de79880b816a57takashi const char **new_type = (const char **)apr_array_push(type_list);
2b6c7b8eb5fbc43564898aedac730df7e91da475trawick if (apr_is_empty_array(type_list)) { /* no mutex type? assume "default" */
b6b8c27b2adcf08eca23d3b7c2de79880b816a57takashi const char **new_type = (const char **)apr_array_push(type_list);
2b6c7b8eb5fbc43564898aedac730df7e91da475trawick while ((elt = (const char **)apr_array_pop(type_list)) != NULL) {
2b6c7b8eb5fbc43564898aedac730df7e91da475trawick mxcfg = apr_hash_get(mxcfg_by_type, type, APR_HASH_KEY_STRING);
2b6c7b8eb5fbc43564898aedac730df7e91da475trawick return apr_psprintf(p, "Mutex type %s is not valid", type);
2b6c7b8eb5fbc43564898aedac730df7e91da475trawick "None is not allowed for mutex type %s",
2b6c7b8eb5fbc43564898aedac730df7e91da475trawick if (mutexdir) { /* retain mutex default if not configured */
11f2c481e1d57bedb3f758565307501e9a2730ddtrawickAP_DECLARE(apr_status_t) ap_mutex_register(apr_pool_t *pconf,
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick const char *type,
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick mutex_cfg_t *mxcfg = apr_pcalloc(pconf, sizeof *mxcfg);
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick if ((options & ~(AP_MUTEX_ALLOW_NONE | AP_MUTEX_DEFAULT_NONE))) {
ead0b57bbeaec5acb14f931b5641962f429dabc9trawick ap_mutex_init(pconf); /* in case this mod's pre-config ran before core's */
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick mxcfg->mech = default_mech; /* usually APR_LOCK_DEFAULT */
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick apr_hash_set(mxcfg_by_type, type, APR_HASH_KEY_STRING, mxcfg);
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick#if APR_USE_FLOCK_SERIALIZE || APR_USE_FCNTL_SERIALIZE
11f2c481e1d57bedb3f758565307501e9a2730ddtrawickstatic const char *get_mutex_filename(apr_pool_t *p, mutex_cfg_t *mxcfg,
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick const char *type,
2b6c7b8eb5fbc43564898aedac730df7e91da475trawick pid_suffix = apr_psprintf(p, ".%" APR_PID_T_FMT, getpid());
11f2c481e1d57bedb3f758565307501e9a2730ddtrawickstatic mutex_cfg_t *mxcfg_lookup(apr_pool_t *p, const char *type)
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick defcfg = apr_hash_get(mxcfg_by_type, "default", APR_HASH_KEY_STRING);
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick /* MUST exist in table, or wasn't registered */
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick mxcfg = apr_hash_get(mxcfg_by_type, type, APR_HASH_KEY_STRING);
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick /* order of precedence:
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * 1. Mutex directive for this mutex
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * 2. Mutex directive for "default"
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * 3. Defaults for this mutex from ap_mutex_register()
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * 4. Global defaults
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick else if (mxcfg->none || mxcfg->mech != APR_LOCK_DEFAULT) {
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick if (!newcfg->none && mutex_needs_file(newcfg->mech) && !newcfg->dir) {
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick /* a file-based mutex mechanism was configured, but
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * without a mutex file directory; go back through
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * the chain to find the directory, store in new
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * mutex cfg structure
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick /* !true if dir not already set: mxcfg->set && defcfg->dir */
11f2c481e1d57bedb3f758565307501e9a2730ddtrawickstatic void log_bad_create_options(server_rec *s, const char *type)
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(00021)
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick "Invalid options were specified when creating the %s mutex",
11f2c481e1d57bedb3f758565307501e9a2730ddtrawickstatic void log_unknown_type(server_rec *s, const char *type)
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(00022)
11f2c481e1d57bedb3f758565307501e9a2730ddtrawickstatic void log_create_failure(apr_status_t rv, server_rec *s, const char *type,
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick const char *fname)
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(00023)
11f2c481e1d57bedb3f758565307501e9a2730ddtrawickstatic void log_perms_failure(apr_status_t rv, server_rec *s, const char *type)
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, APLOGNO(00024)
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick "Couldn't set permissions on the %s mutex; "
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick "check User and Group directives",
11f2c481e1d57bedb3f758565307501e9a2730ddtrawickAP_DECLARE(apr_status_t) ap_global_mutex_create(apr_global_mutex_t **mutex,
6a00621903eff76c1a3ebc3ee46f5e59a492bf77wrowe const char **name,
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick const char *type,
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick fname = get_mutex_filename(p, mxcfg, type, instance_id);
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick rv = apr_global_mutex_create(mutex, fname, mxcfg->mech, p);
11f2c481e1d57bedb3f758565307501e9a2730ddtrawickAP_DECLARE(apr_status_t) ap_proc_mutex_create(apr_proc_mutex_t **mutex,
6a00621903eff76c1a3ebc3ee46f5e59a492bf77wrowe const char **name,
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick const char *type,
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick fname = get_mutex_filename(p, mxcfg, type, instance_id);
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick rv = apr_proc_mutex_create(mutex, fname, mxcfg->mech, p);
67746e0d18eeceb247fc940148c9b4d358929643sfAP_CORE_DECLARE(void) ap_dump_mutexes(apr_pool_t *p, server_rec *s, apr_file_t *out)
67746e0d18eeceb247fc940148c9b4d358929643sf mutex_cfg_t *defcfg = apr_hash_get(mxcfg_by_type, "default", APR_HASH_KEY_STRING);
67746e0d18eeceb247fc940148c9b4d358929643sf for (idx = apr_hash_first(p, mxcfg_by_type); idx; idx = apr_hash_next(idx))
67746e0d18eeceb247fc940148c9b4d358929643sf apr_file_printf(out, "Mutex %s: using_defaults\n", name);
67746e0d18eeceb247fc940148c9b4d358929643sf apr_file_printf(out, "Mutex %s: dir=\"%s\" mechanism=%s %s\n", name, dir, mech,