f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna/* Licensed to the Apache Software Foundation (ASF) under one or more
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna * contributor license agreements. See the NOTICE file distributed with
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna * this work for additional information regarding copyright ownership.
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna * The ASF licenses this file to You under the Apache License, Version 2.0
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna * (the "License"); you may not use this file except in compliance with
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna * the License. You may obtain a copy of the License at
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna *
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna * http://www.apache.org/licenses/LICENSE-2.0
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna *
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna * Unless required by applicable law or agreed to in writing, software
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna * distributed under the License is distributed on an "AS IS" BASIS,
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna * See the License for the specific language governing permissions and
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna * limitations under the License.
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna */
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna#include "httpd.h"
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna#include "http_config.h"
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna#include "simple_types.h"
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna#include "simple_event.h"
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna#include "simple_run.h"
f47612d41722d85fe2d698c43316a36fbccd4685pquerna#include "http_log.h"
e811d6e3aec5ec21c6de99652feff5d1f883daa6pquerna#include "simple_children.h"
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna#include "apr_hash.h"
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna
f47612d41722d85fe2d698c43316a36fbccd4685pquerna#include <unistd.h> /* For fork() */
f47612d41722d85fe2d698c43316a36fbccd4685pquerna
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna#define SPAWN_CHILDREN_INTERVAL (apr_time_from_sec(5))
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna
36ef8f77bffe75d1aa327882be1b5bdbe2ff567asfAPLOG_USE_MODULE(mpm_simple);
36ef8f77bffe75d1aa327882be1b5bdbe2ff567asf
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquernastatic void simple_kill_random_child(simple_core_t * sc)
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna{
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna /* See comment in simple_spawn_child for why we check here. */
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna if (!sc->run_single_process) {
f47612d41722d85fe2d698c43316a36fbccd4685pquerna apr_hash_index_t *hi;
f47612d41722d85fe2d698c43316a36fbccd4685pquerna simple_child_t *child = NULL;
f47612d41722d85fe2d698c43316a36fbccd4685pquerna
f47612d41722d85fe2d698c43316a36fbccd4685pquerna apr_thread_mutex_lock(sc->mtx);
f47612d41722d85fe2d698c43316a36fbccd4685pquerna hi = apr_hash_first(sc->pool, sc->children);
f47612d41722d85fe2d698c43316a36fbccd4685pquerna if (hi != NULL) {
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim apr_hash_this(hi, NULL, NULL, (void **)&child);
f47612d41722d85fe2d698c43316a36fbccd4685pquerna apr_hash_set(sc->children, &child->pid, sizeof(child->pid), NULL);
f47612d41722d85fe2d698c43316a36fbccd4685pquerna }
f47612d41722d85fe2d698c43316a36fbccd4685pquerna apr_thread_mutex_unlock(sc->mtx);
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
f47612d41722d85fe2d698c43316a36fbccd4685pquerna if (child != NULL) {
f47612d41722d85fe2d698c43316a36fbccd4685pquerna kill(child->pid, 9);
f47612d41722d85fe2d698c43316a36fbccd4685pquerna /* TODO: recycle child object */
f47612d41722d85fe2d698c43316a36fbccd4685pquerna }
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna }
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna}
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna
f47612d41722d85fe2d698c43316a36fbccd4685pquernastatic void clean_child_exit(int code) __attribute__ ((noreturn));
f47612d41722d85fe2d698c43316a36fbccd4685pquernastatic void clean_child_exit(int code)
f47612d41722d85fe2d698c43316a36fbccd4685pquerna{
f47612d41722d85fe2d698c43316a36fbccd4685pquerna /* TODO: Pool cleanups.... sigh. */
f47612d41722d85fe2d698c43316a36fbccd4685pquerna exit(code);
f47612d41722d85fe2d698c43316a36fbccd4685pquerna}
f47612d41722d85fe2d698c43316a36fbccd4685pquerna
f47612d41722d85fe2d698c43316a36fbccd4685pquernastatic int simple_spawn_child(simple_core_t * sc)
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna{
f47612d41722d85fe2d698c43316a36fbccd4685pquerna pid_t pid = 0;
f47612d41722d85fe2d698c43316a36fbccd4685pquerna int rv = 0;
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* Although we could cut this off 'earlier', and not even invoke this
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna * function, I would like to keep the functions invoked when in debug mode
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna * to be as close as possible to those when not in debug... So, we just skip
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna * the actual spawn itself, but go through all of the motions...
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna */
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna if (!sc->run_single_process) {
f47612d41722d85fe2d698c43316a36fbccd4685pquerna if (sc->spawn_via == SIMPLE_SPAWN_FORK) {
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
f47612d41722d85fe2d698c43316a36fbccd4685pquerna pid = fork();
f47612d41722d85fe2d698c43316a36fbccd4685pquerna if (pid == -1) {
f47612d41722d85fe2d698c43316a36fbccd4685pquerna rv = errno;
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(00245)
f47612d41722d85fe2d698c43316a36fbccd4685pquerna "simple_spawn_child: Unable to fork new process");
f47612d41722d85fe2d698c43316a36fbccd4685pquerna return rv;
f47612d41722d85fe2d698c43316a36fbccd4685pquerna }
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
f47612d41722d85fe2d698c43316a36fbccd4685pquerna if (pid == 0) {
f47612d41722d85fe2d698c43316a36fbccd4685pquerna /* this is the child process */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
f47612d41722d85fe2d698c43316a36fbccd4685pquerna rv = simple_child_loop(sc);
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna
f47612d41722d85fe2d698c43316a36fbccd4685pquerna if (rv) {
f47612d41722d85fe2d698c43316a36fbccd4685pquerna clean_child_exit(APEXIT_CHILDFATAL);
f47612d41722d85fe2d698c43316a36fbccd4685pquerna }
f47612d41722d85fe2d698c43316a36fbccd4685pquerna else {
f47612d41722d85fe2d698c43316a36fbccd4685pquerna clean_child_exit(0);
f47612d41722d85fe2d698c43316a36fbccd4685pquerna }
f47612d41722d85fe2d698c43316a36fbccd4685pquerna }
f47612d41722d85fe2d698c43316a36fbccd4685pquerna }
f47612d41722d85fe2d698c43316a36fbccd4685pquerna else {
f47612d41722d85fe2d698c43316a36fbccd4685pquerna /* TODO: SIMPLE_SPAWN_EXEC */
f47612d41722d85fe2d698c43316a36fbccd4685pquerna abort();
f47612d41722d85fe2d698c43316a36fbccd4685pquerna }
f47612d41722d85fe2d698c43316a36fbccd4685pquerna }
f47612d41722d85fe2d698c43316a36fbccd4685pquerna
f47612d41722d85fe2d698c43316a36fbccd4685pquerna if (pid != 0) {
f47612d41722d85fe2d698c43316a36fbccd4685pquerna simple_child_t *child;
f47612d41722d85fe2d698c43316a36fbccd4685pquerna
f47612d41722d85fe2d698c43316a36fbccd4685pquerna apr_thread_mutex_lock(sc->mtx);
f47612d41722d85fe2d698c43316a36fbccd4685pquerna
f47612d41722d85fe2d698c43316a36fbccd4685pquerna child = apr_palloc(sc->pool, sizeof(simple_child_t));
f47612d41722d85fe2d698c43316a36fbccd4685pquerna child->pid = pid;
f47612d41722d85fe2d698c43316a36fbccd4685pquerna apr_hash_set(sc->children, &child->pid, sizeof(child->pid), child);
f47612d41722d85fe2d698c43316a36fbccd4685pquerna
f47612d41722d85fe2d698c43316a36fbccd4685pquerna apr_thread_mutex_unlock(sc->mtx);
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna }
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
f47612d41722d85fe2d698c43316a36fbccd4685pquerna return 0;
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna}
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquernavoid simple_check_children_size(simple_core_t * sc, void *baton)
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna{
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna unsigned int count;
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna int wanted;
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna int i;
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna simple_register_timer(sc,
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna simple_check_children_size,
6881fda812136efa364537ad49964b509a345bd2pquerna NULL, SPAWN_CHILDREN_INTERVAL,
6881fda812136efa364537ad49964b509a345bd2pquerna sc->pool);
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna if (sc->run_single_process && sc->restart_num == 2) {
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna static int run = 0;
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* This is kinda of hack, but rather than spawning a child process,
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna * we register the normal IO handlers in the main event loop....
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna */
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna if (run == 0) {
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna simple_single_process_hack(sc);
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna run++;
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna }
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna }
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna {
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna apr_thread_mutex_lock(sc->mtx);
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna count = apr_hash_count(sc->children);
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna wanted = sc->procmgr.proc_count;
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna apr_thread_mutex_unlock(sc->mtx);
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna }
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna if (count > wanted) {
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna /* kill some kids */
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna int to_kill = count - wanted;
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna for (i = 0; i < to_kill; i++) {
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna simple_kill_random_child(sc);
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna }
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna }
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna else if (count < wanted) {
f47612d41722d85fe2d698c43316a36fbccd4685pquerna int rv = 0;
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna /* spawn some kids */
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna int to_spawn = wanted - count;
f47612d41722d85fe2d698c43316a36fbccd4685pquerna for (i = 0; rv == 0 && i < to_spawn; i++) {
f47612d41722d85fe2d698c43316a36fbccd4685pquerna rv = simple_spawn_child(sc);
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna }
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna }
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna else {
52a5101047d0148d33df1f9f4f77b24bce7fdf70pquerna /* juuuuust right. */
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna }
f997d134bcee6bfa4cd87b69acee96e80c5a358bpquerna}