⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpm_netware.c

📁 apache的软件linux版本
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * httpd.c: simple http daemon for answering WWW file requests * *  * 03-21-93  Rob McCool wrote original code (up to NCSA HTTPd 1.3) *  * 03-06-95  blong *  changed server number for child-alone processes to 0 and changed name *   of processes * * 03-10-95  blong *      Added numerous speed hacks proposed by Robert S. Thau (rst@ai.mit.edu)  *      including set group before fork, and call gettime before to fork *      to set up libraries. * * 04-14-95  rst / rh *      Brandon's code snarfed from NCSA 1.4, but tinkered to work with the *      Apache server, and also to have child processes do accept() directly. * * April-July '95 rst *      Extensive rework for Apache. */#include "apr.h"#include "apr_portable.h"#include "apr_strings.h"#include "apr_thread_proc.h"#include "apr_signal.h"#include "apr_tables.h"#include "apr_getopt.h"#include "apr_thread_mutex.h"#define APR_WANT_STDIO#define APR_WANT_STRFUNC#include "apr_want.h"#if APR_HAVE_UNISTD_H#include <unistd.h>#endif#if APR_HAVE_SYS_TYPES_H#include <sys/types.h>#endif#define CORE_PRIVATE#include "ap_config.h"#include "httpd.h"#include "mpm_default.h"#include "http_main.h"#include "http_log.h"#include "http_config.h"#include "http_core.h"             /* for get_remote_host */#include "http_connection.h"#include "scoreboard.h"#include "ap_mpm.h"#include "mpm_common.h"#include "ap_listen.h"#include "ap_mmn.h"#ifdef HAVE_TIME_H#include <time.h>#endif#include <signal.h>#include <netware.h>#include <nks/netware.h>#include <library.h>#include <screen.h>/* Limit on the total --- clients will be locked out if more servers than * this are needed.  It is intended solely to keep the server from crashing * when things get out of hand. * * We keep a hard maximum number of servers, for two reasons --- first off, * in case something goes seriously wrong, we want to stop the fork bomb * short of actually crashing the machine we're running on by filling some * kernel table.  Secondly, it keeps the size of the scoreboard file small * enough that we can read the whole thing without worrying too much about * the overhead. */#ifndef HARD_SERVER_LIMIT#define HARD_SERVER_LIMIT 1#endif#define WORKER_DEAD         SERVER_DEAD#define WORKER_STARTING     SERVER_STARTING#define WORKER_READY        SERVER_READY#define WORKER_IDLE_KILL    SERVER_IDLE_KILL/* config globals */int ap_threads_per_child=0;         /* Worker threads per child */int ap_thread_stack_size=65536;static int ap_threads_to_start=0;static int ap_threads_min_free=0;static int ap_threads_max_free=0;static int ap_threads_limit=0;static int mpm_state = AP_MPMQ_STARTING;/* * The max child slot ever assigned, preserved across restarts.  Necessary * to deal with MaxClients changes across SIGWINCH restarts.  We use this * value to optimize routines that have to scan the entire scoreboard. */int ap_max_workers_limit = -1;server_rec *ap_server_conf;/* *Non*-shared http_main globals... */int hold_screen_on_exit = 0; /* Indicates whether the screen should be held open */static fd_set listenfds;static int listenmaxfd;static apr_pool_t *pconf;               /* Pool for config stuff */static apr_pool_t *pmain;               /* Pool for httpd child stuff */static pid_t ap_my_pid;  /* it seems silly to call getpid all the time */static char *ap_my_addrspace = NULL;static int die_now = 0;/* Keep track of the number of worker threads currently active */static unsigned long worker_thread_count;static int request_count;/*  Structure used to register/deregister a console handler with the OS */static int InstallConsoleHandler(void);static void RemoveConsoleHandler(void);static int CommandLineInterpreter(scr_t screenID, const char *commandLine);static  CommandParser_t ConsoleHandler = {0, NULL, 0};#define HANDLEDCOMMAND  0#define NOTMYCOMMAND    1static int show_settings = 0;//#define DBINFO_ON//#define DBPRINT_ON#ifdef DBPRINT_ON#define DBPRINT0(s) printf(s)#define DBPRINT1(s,v1) printf(s,v1)#define DBPRINT2(s,v1,v2) printf(s,v1,v2)#else#define DBPRINT0(s)#define DBPRINT1(s,v1)#define DBPRINT2(s,v1,v2)#endif/* volatile just in case */static int volatile shutdown_pending;static int volatile restart_pending;static int volatile is_graceful;static int volatile wait_to_finish=1;ap_generation_t volatile ap_my_generation=0;/* a clean exit from a child with proper cleanup */static void clean_child_exit(int code, int worker_num, apr_pool_t *ptrans,                              apr_bucket_alloc_t *bucket_alloc) __attribute__ ((noreturn));static void clean_child_exit(int code, int worker_num, apr_pool_t *ptrans,                              apr_bucket_alloc_t *bucket_alloc){    apr_bucket_alloc_destroy(bucket_alloc);    if (!shutdown_pending) {        apr_pool_destroy(ptrans);    }    atomic_dec (&worker_thread_count);    if (worker_num >=0)        ap_update_child_status_from_indexes(0, worker_num, WORKER_DEAD,                                             (request_rec *) NULL);    NXThreadExit((void*)&code);}AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result){    switch(query_code){        case AP_MPMQ_MAX_DAEMON_USED:            *result = 1;            return APR_SUCCESS;        case AP_MPMQ_IS_THREADED:            *result = AP_MPMQ_DYNAMIC;            return APR_SUCCESS;        case AP_MPMQ_IS_FORKED:            *result = AP_MPMQ_NOT_SUPPORTED;            return APR_SUCCESS;        case AP_MPMQ_HARD_LIMIT_DAEMONS:            *result = HARD_SERVER_LIMIT;            return APR_SUCCESS;        case AP_MPMQ_HARD_LIMIT_THREADS:            *result = HARD_THREAD_LIMIT;            return APR_SUCCESS;        case AP_MPMQ_MAX_THREADS:            *result = ap_threads_limit;            return APR_SUCCESS;        case AP_MPMQ_MIN_SPARE_DAEMONS:            *result = 0;            return APR_SUCCESS;        case AP_MPMQ_MIN_SPARE_THREADS:            *result = ap_threads_min_free;            return APR_SUCCESS;        case AP_MPMQ_MAX_SPARE_DAEMONS:            *result = 0;            return APR_SUCCESS;        case AP_MPMQ_MAX_SPARE_THREADS:            *result = ap_threads_max_free;            return APR_SUCCESS;        case AP_MPMQ_MAX_REQUESTS_DAEMON:            *result = ap_max_requests_per_child;            return APR_SUCCESS;        case AP_MPMQ_MAX_DAEMONS:            *result = 1;            return APR_SUCCESS;        case AP_MPMQ_MPM_STATE:            *result = mpm_state;            return APR_SUCCESS;    }    return APR_ENOTIMPL;}/***************************************************************** * Connection structures and accounting... */static void mpm_term(void){    RemoveConsoleHandler();    wait_to_finish = 0;    NXThreadYield();}static void sig_term(int sig){    if (shutdown_pending == 1) {        /* Um, is this _probably_ not an error, if the user has         * tried to do a shutdown twice quickly, so we won't         * worry about reporting it.         */        return;    }    shutdown_pending = 1;    DBPRINT0 ("waiting for threads\n");    while (wait_to_finish) {        apr_thread_yield();    }    DBPRINT0 ("goodbye\n");}/* restart() is the signal handler for SIGHUP and SIGWINCH * in the parent process, unless running in ONE_PROCESS mode */static void restart(void){    if (restart_pending == 1) {        /* Probably not an error - don't bother reporting it */        return;    }    restart_pending = 1;    is_graceful = 1;}static void set_signals(void){    apr_signal(SIGTERM, sig_term);    apr_signal(SIGABRT, sig_term);}int nlmUnloadSignaled(int wait){    shutdown_pending = 1;    if (wait) {        while (wait_to_finish) {            NXThreadYield();        }    }    return 0;}/***************************************************************** * Child process main loop. * The following vars are static to avoid getting clobbered by longjmp(); * they are really private to child_main. */int ap_graceful_stop_signalled(void){    /* not ever called anymore... */    return 0;}#define MAX_WB_RETRIES  3#ifdef DBINFO_ONstatic int would_block = 0;static int retry_success = 0;static int retry_fail = 0;static int avg_retries = 0;#endif/*static */void worker_main(void *arg){    ap_listen_rec *lr, *first_lr, *last_lr = NULL;    apr_pool_t *ptrans;    apr_pool_t *pbucket;    apr_allocator_t *allocator;    apr_bucket_alloc_t *bucket_alloc;    conn_rec *current_conn;    apr_status_t stat = APR_EINIT;    ap_sb_handle_t *sbh;    int my_worker_num = (int)arg;    apr_socket_t *csd = NULL;    int requests_this_child = 0;    apr_socket_t *sd = NULL;    fd_set main_fds;    int sockdes;    int srv;    struct timeval tv;    int wouldblock_retry;    tv.tv_sec = 1;    tv.tv_usec = 0;    apr_allocator_create(&allocator);    apr_allocator_max_free_set(allocator, ap_max_mem_free);    apr_pool_create_ex(&ptrans, pmain, NULL, allocator);    apr_allocator_owner_set(allocator, ptrans);    apr_pool_tag(ptrans, "transaction");    bucket_alloc = apr_bucket_alloc_create_ex(allocator);    atomic_inc (&worker_thread_count);    while (!die_now) {        /*        * (Re)initialize this child to a pre-connection state.        */        current_conn = NULL;        apr_pool_clear(ptrans);        if ((ap_max_requests_per_child > 0            && requests_this_child++ >= ap_max_requests_per_child)) {            DBPRINT1 ("\n**Thread slot %d is shutting down", my_worker_num);            clean_child_exit(0, my_worker_num, ptrans, bucket_alloc);        }        ap_update_child_status_from_indexes(0, my_worker_num, WORKER_READY,                                             (request_rec *) NULL);        /*        * Wait for an acceptable connection to arrive.        */        for (;;) {            if (shutdown_pending || restart_pending || (ap_scoreboard_image->servers[0][my_worker_num].status == WORKER_IDLE_KILL)) {                DBPRINT1 ("\nThread slot %d is shutting down\n", my_worker_num);                clean_child_exit(0, my_worker_num, ptrans, bucket_alloc);            }            /* Check the listen queue on all sockets for requests */            memcpy(&main_fds, &listenfds, sizeof(fd_set));            srv = select(listenmaxfd + 1, &main_fds, NULL, NULL, &tv);            if (srv <= 0) {                if (srv < 0) {                    ap_log_error(APLOG_MARK, APLOG_NOTICE, WSAGetLastError(), ap_server_conf,                        "select() failed on listen socket");                    apr_thread_yield();                }                continue;            }            /* remember the last_lr we searched last time around so that            we don't end up starving any particular listening socket */            if (last_lr == NULL) {                lr = ap_listeners;            }            else {                lr = last_lr->next;                if (!lr)                    lr = ap_listeners;            }            first_lr = lr;            do {                apr_os_sock_get(&sockdes, lr->sd);                if (FD_ISSET(sockdes, &main_fds))                    goto got_listener;                lr = lr->next;                if (!lr)                    lr = ap_listeners;            } while (lr != first_lr);            /* if we get here, something unexpected happened. Go back            into the select state and try again.            */            continue;        got_listener:            last_lr = lr;            sd = lr->sd;            wouldblock_retry = MAX_WB_RETRIES;            while (wouldblock_retry) {                if ((stat = apr_accept(&csd, sd, ptrans)) == APR_SUCCESS) {                    break;                }                else {                    /* if the error is a wouldblock then maybe we were too                        quick try to pull the next request from the listen                         queue.  Try a few more times then return to our idle

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -