scoreboard.c revision 8232302b6fc415a7ef743b65754f7d4240a5a95a
842ae4bd224140319ae7feec1872b93dfd491143fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding * contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding * this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding * The ASF licenses this file to You under the Apache License, Version 2.0
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"); you may not use this file except in compliance with
842ae4bd224140319ae7feec1872b93dfd491143fielding * the License. You may obtain a copy of the License at
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * Unless required by applicable law or agreed to in writing, software
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * distributed under the License is distributed on an "AS IS" BASIS,
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * See the License for the specific language governing permissions and
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * limitations under the License.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm/* we know core's module_index is 0 */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE_DATA scoreboard *ap_scoreboard_image = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE_DATA const char *ap_scoreboard_fname = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinconst char * ap_set_scoreboard(cmd_parms *cmd, void *dummy,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
5b03ba47ff7225cacb131f14b019332af27da960gstein/* Default to false when mod_status is not loaded */
5b03ba47ff7225cacb131f14b019332af27da960gsteinconst char *ap_set_extended_status(cmd_parms *cmd, void *dummy, int arg)
5b03ba47ff7225cacb131f14b019332af27da960gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinconst char *ap_set_reqtail(cmd_parms *cmd, void *dummy, int arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
691db92094897494d6c31326108da20088bc175etrawickstatic /* but must be exported to mpm_winnt */
f4c310fd2555c6faca1f980f00b161eadb089023gstein * This function should be renamed to cleanup_shared
f4c310fd2555c6faca1f980f00b161eadb089023gstein * and it should handle cleaning up a scoreboard shared
e8f95a682820a599fe41b22977010636be5c2717jim * between processes using any form of IPC (file, shared memory
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe * segment, etc.). Leave it as is now because it is being used
f4c310fd2555c6faca1f980f00b161eadb089023gstein * by various MPMs.
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit);
f4c310fd2555c6faca1f980f00b161eadb089023gstein scoreboard_size += sizeof(process_score) * server_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein scoreboard_size += sizeof(worker_score) * server_limit * thread_limit;
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe pfn_ap_logio_get_last_bytes = APR_RETRIEVE_OPTIONAL_FN(ap_logio_get_last_bytes);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(void) ap_init_scoreboard(void *shared_score)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_calloc(1, sizeof(scoreboard) + server_limit * sizeof(worker_score *));
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->global = (global_score *)more_storage;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->parent = (process_score *)more_storage;
f4c310fd2555c6faca1f980f00b161eadb089023gstein more_storage += sizeof(process_score) * server_limit;
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe (worker_score **)((char*)ap_scoreboard_image + sizeof(scoreboard));
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; i < server_limit; i++) {
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski ap_scoreboard_image->servers[i] = (worker_score *)more_storage;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_assert(more_storage == (char*)shared_score + scoreboard_size);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->global->server_limit = server_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->global->thread_limit = thread_limit;
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe * Create a name-based scoreboard in the given pool using the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * given filename.
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t create_namebased_scoreboard(apr_pool_t *pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *fname)
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* The shared memory file must not exist before we create the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * segment. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = apr_shm_create(&ap_scoreboard_shm, scoreboard_size, fname, pool);
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00001)
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz "unable to create or access scoreboard \"%s\" "
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* APR_HAS_SHARED_MEMORY */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* ToDo: This function should be made to handle setting up
f4c310fd2555c6faca1f980f00b161eadb089023gstein * a scoreboard shared between processes using any IPC technique,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * not just a shared memory segment
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* We don't want to have to recreate the scoreboard after
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe * restarts, so we'll create a global pool and never clean it.
48f35e10f195dd594d75738fc536bb885eda537cgstein ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00002)
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Fatal error: unable to create global pool "
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe "for use by the scoreboard");
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe /* The config says to create a name-based shmem */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* make sure it's an absolute pathname */
48f35e10f195dd594d75738fc536bb885eda537cgstein fname = ap_runtime_dir_relative(pconf, ap_scoreboard_fname);
48f35e10f195dd594d75738fc536bb885eda537cgstein ap_log_error(APLOG_MARK, APLOG_CRIT, APR_EBADPATH, ap_server_conf, APLOGNO(00003)
48f35e10f195dd594d75738fc536bb885eda537cgstein "Fatal error: Invalid Scoreboard path %s",
48f35e10f195dd594d75738fc536bb885eda537cgstein return create_namebased_scoreboard(global_pool, fname);
48f35e10f195dd594d75738fc536bb885eda537cgstein else { /* config didn't specify, we get to choose shmem type */
48f35e10f195dd594d75738fc536bb885eda537cgstein rv = apr_shm_create(&ap_scoreboard_shm, scoreboard_size, NULL,
7b6ba9c468f26bdb3492d5e8cb79628a3b04e8c8wrowe ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00004)
48f35e10f195dd594d75738fc536bb885eda537cgstein "Unable to create or access scoreboard "
48f35e10f195dd594d75738fc536bb885eda537cgstein "(anonymous shared memory failure)");
48f35e10f195dd594d75738fc536bb885eda537cgstein /* Make up a filename and do name-based shmem */
48f35e10f195dd594d75738fc536bb885eda537cgstein /* Make sure it's an absolute pathname */
c1b808d160bfb5c849263be8d4acff600853a328trawick fname = ap_runtime_dir_relative(pconf, ap_scoreboard_fname);
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein return create_namebased_scoreboard(global_pool, fname);
77c2148c53e0a4a20a80af735caa4e0e6bd448e0gstein#endif /* APR_HAS_SHARED_MEMORY */
48f35e10f195dd594d75738fc536bb885eda537cgstein/* If detach is non-zero, this is a separate child process,
48f35e10f195dd594d75738fc536bb885eda537cgstein * if zero, it is a forked child.
48f35e10f195dd594d75738fc536bb885eda537cgsteinAP_DECLARE(apr_status_t) ap_reopen_scoreboard(apr_pool_t *p, apr_shm_t **shm,
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (apr_shm_size_get(ap_scoreboard_shm) < scoreboard_size) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_CRIT, 0, ap_server_conf, APLOGNO(00005)
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Fatal error: shared scoreboard too small for child!");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* everything will be cleared shortly */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Create or reinit an existing scoreboard. The MPM can control whether
f4c310fd2555c6faca1f980f00b161eadb089023gstein * the scoreboard is shared across multiple processes or not
f4c310fd2555c6faca1f980f00b161eadb089023gsteinint ap_create_scoreboard(apr_pool_t *p, ap_scoreboard_e sb_type)
f4c310fd2555c6faca1f980f00b161eadb089023gstein pfn_ap_logio_get_last_bytes = APR_RETRIEVE_OPTIONAL_FN(ap_logio_get_last_bytes);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->global->restart_time = apr_time_now();
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; i < server_limit; i++) {
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe if (rv || !(sb_shared = apr_shm_baseaddr_get(ap_scoreboard_shm))) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* A simple malloc will suffice */
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe ap_scoreboard_image->global->restart_time = apr_time_now();
f39230a531b23d94f86a087963299bbe2e431a4agstein apr_pool_cleanup_register(p, NULL, ap_cleanup_scoreboard, apr_pool_cleanup_null);
f39230a531b23d94f86a087963299bbe2e431a4agstein/* Routines called to deal with the scoreboard image
f39230a531b23d94f86a087963299bbe2e431a4agstein * --- note that we do *not* need write locks, since update_child_status
1e2133fe37e6cbcd683233057ef62236bc8e5826trawick * only updates a *single* record in place, and only one process writes to
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * a given scoreboard slot at a time (either the child process owning that
f39230a531b23d94f86a087963299bbe2e431a4agstein * slot, or the parent, noting that the child has died).
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * As a final note --- setting the score entry to getpid() is always safe,
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein * since when the parent is writing an entry, it's only noting SERVER_DEAD
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gsteinAP_DECLARE(void) ap_increment_counts(ap_sb_handle_t *sb, request_rec *r)
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein ws = &ap_scoreboard_image->servers[sb->child_num][sb->thread_num];
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein else if (r->method_number == M_GET && r->method[0] == 'H') {
f39230a531b23d94f86a087963299bbe2e431a4agstein ap_mpm_query(AP_MPMQ_MAX_DAEMONS, &max_daemons_limit);
f39230a531b23d94f86a087963299bbe2e431a4agstein for (i = 0; i < max_daemons_limit; ++i) {
ab78b55c6dc4431d2c68d6bb4d169ba1554290a8gstein if (ap_scoreboard_image->parent[i].pid == pid->pid) {
f39230a531b23d94f86a087963299bbe2e431a4agsteinAP_DECLARE(void) ap_create_sb_handle(ap_sb_handle_t **new_sbh, apr_pool_t *p,
f39230a531b23d94f86a087963299bbe2e431a4agstein *new_sbh = (ap_sb_handle_t *)apr_palloc(p, sizeof(ap_sb_handle_t));
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinstatic void copy_request(char *rbuf, apr_size_t rbuflen, request_rec *r)
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein return; /* short circuit below */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein /* Don't reveal the password in the server-status view */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein /* now figure out if we copy over the 1st rbuflen chars or the last */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein /* it all fits anyway */
b5989e567e4fac5b3ab1252024ae19b0a54893a7gsteinstatic int update_child_status_internal(int child_num,
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein ws = &ap_scoreboard_image->servers[child_num][thread_num];
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein ws->thread_num = child_num * thread_limit + thread_num;
b5989e567e4fac5b3ab1252024ae19b0a54893a7gstein if (status == SERVER_READY || status == SERVER_DEAD) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Reset individual counters
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_cpystrn(ws->client, ap_get_remote_host(c, r->per_dir_config,
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantz apr_snprintf(ws->vhost, sizeof(ws->vhost), "%s:%d",
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm else if (c) {
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(int) ap_update_child_status_from_indexes(int child_num,
6f15570e3adc0faf87bf55f70857028276fc9e32wrowe return update_child_status_internal(child_num, thread_num, status,
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(int) ap_update_child_status(ap_sb_handle_t *sbh, int status,
f4c310fd2555c6faca1f980f00b161eadb089023gstein return update_child_status_internal(sbh->child_num, sbh->thread_num,
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(int) ap_update_child_status_from_conn(ap_sb_handle_t *sbh, int status,
f4c310fd2555c6faca1f980f00b161eadb089023gstein return update_child_status_internal(sbh->child_num, sbh->thread_num,
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(void) ap_time_process_request(ap_sb_handle_t *sbh, int status)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ws = &ap_scoreboard_image->servers[sbh->child_num][sbh->thread_num];
6f15570e3adc0faf87bf55f70857028276fc9e32wroweAP_DECLARE(worker_score *) ap_get_scoreboard_worker_from_indexes(int x, int y)
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton if (((x < 0) || (x >= server_limit)) ||
42f2b4b0e9b84dfd8acbb9c0da18a07c664e30a1jorton ((y < 0) || (y >= thread_limit))) {
5a8f3bcf803321e69b226d3b98314305a68a586cjerenkrantzAP_DECLARE(worker_score *) ap_get_scoreboard_worker(ap_sb_handle_t *sbh)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return ap_get_scoreboard_worker_from_indexes(sbh->child_num,
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(process_score *) ap_get_scoreboard_process(int x)
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((x < 0) || (x >= server_limit)) {