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

📄 mpm_winnt.c

📁 最新apache的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
 * of this event means that the child process has exited prematurely * due to a seg fault or other irrecoverable error. For server * robustness, master_main will restart the child process under this  * condtion. * * master_main uses the child_exit_event to signal the child process * to exit. **********************************************************************/#define NUM_WAIT_HANDLES 3#define CHILD_HANDLE     0#define SHUTDOWN_HANDLE  1#define RESTART_HANDLE   2static int master_main(server_rec *s, HANDLE shutdown_event, HANDLE restart_event){    int rv, cld;    int restart_pending;    int shutdown_pending;    HANDLE child_exit_event;    HANDLE event_handles[NUM_WAIT_HANDLES];    DWORD child_pid;    restart_pending = shutdown_pending = 0;    event_handles[SHUTDOWN_HANDLE] = shutdown_event;    event_handles[RESTART_HANDLE] = restart_event;    /* Create a single child process */    rv = create_process(pconf, &event_handles[CHILD_HANDLE],                         &child_exit_event, &child_pid);    if (rv < 0)     {        ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,                     "master_main: create child process failed. Exiting.");        shutdown_pending = 1;        goto die_now;    }    if (!strcasecmp(signal_arg, "runservice")) {        mpm_service_started();    }    /* Update the scoreboard. Note that there is only a single active     * child at once.     */    ap_scoreboard_image->parent[0].quiescing = 0;    ap_scoreboard_image->parent[0].pid = child_pid;    /* Wait for shutdown or restart events or for child death */    winnt_mpm_state = AP_MPMQ_RUNNING;    rv = WaitForMultipleObjects(NUM_WAIT_HANDLES, (HANDLE *) event_handles, FALSE, INFINITE);    cld = rv - WAIT_OBJECT_0;    if (rv == WAIT_FAILED) {        /* Something serious is wrong */        ap_log_error(APLOG_MARK,APLOG_CRIT, apr_get_os_error(), ap_server_conf,                     "master_main: WaitForMultipeObjects WAIT_FAILED -- doing server shutdown");        shutdown_pending = 1;    }    else if (rv == WAIT_TIMEOUT) {        /* Hey, this cannot happen */        ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), s,                     "master_main: WaitForMultipeObjects with INFINITE wait exited with WAIT_TIMEOUT");        shutdown_pending = 1;    }    else if (cld == SHUTDOWN_HANDLE) {        /* shutdown_event signalled */        shutdown_pending = 1;        ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, s,                      "Parent: Received shutdown signal -- Shutting down the server.");        if (ResetEvent(shutdown_event) == 0) {            ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), s,                         "ResetEvent(shutdown_event)");        }    }    else if (cld == RESTART_HANDLE) {        /* Received a restart event. Prepare the restart_event to be reused          * then signal the child process to exit.          */        restart_pending = 1;        ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s,                      "Parent: Received restart signal -- Restarting the server.");        if (ResetEvent(restart_event) == 0) {            ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), s,                         "Parent: ResetEvent(restart_event) failed.");        }        if (SetEvent(child_exit_event) == 0) {            ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), s,                         "Parent: SetEvent for child process %d failed.",                          event_handles[CHILD_HANDLE]);        }        /* Don't wait to verify that the child process really exits,          * just move on with the restart.         */        CloseHandle(event_handles[CHILD_HANDLE]);        event_handles[CHILD_HANDLE] = NULL;    }    else {        /* The child process exited prematurely due to a fatal error. */        DWORD exitcode;        if (!GetExitCodeProcess(event_handles[CHILD_HANDLE], &exitcode)) {            /* HUH? We did exit, didn't we? */            exitcode = APEXIT_CHILDFATAL;        }        if (   exitcode == APEXIT_CHILDFATAL             || exitcode == APEXIT_CHILDINIT            || exitcode == APEXIT_INIT) {            ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,                          "Parent: child process exited with status %u -- Aborting.", exitcode);        }        else {            int i;            restart_pending = 1;            ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, ap_server_conf,                          "Parent: child process exited with status %u -- Restarting.", exitcode);            for (i = 0; i < ap_threads_per_child; i++) {                ap_update_child_status_from_indexes(0, i, SERVER_DEAD, NULL);            }        }        CloseHandle(event_handles[CHILD_HANDLE]);        event_handles[CHILD_HANDLE] = NULL;    }    if (restart_pending) {        ++ap_my_generation;        ap_scoreboard_image->global->running_generation = ap_my_generation;    }die_now:    if (shutdown_pending)     {        int timeout = 30000;  /* Timeout is milliseconds */        winnt_mpm_state = AP_MPMQ_STOPPING;        /* This shutdown is only marginally graceful. We will give the          * child a bit of time to exit gracefully. If the time expires,         * the child will be wacked.         */        if (!strcasecmp(signal_arg, "runservice")) {            mpm_service_stopping();        }        /* Signal the child processes to exit */        if (SetEvent(child_exit_event) == 0) {                ap_log_error(APLOG_MARK,APLOG_ERR, apr_get_os_error(), ap_server_conf,                             "Parent: SetEvent for child process %d failed", event_handles[CHILD_HANDLE]);        }        if (event_handles[CHILD_HANDLE]) {            rv = WaitForSingleObject(event_handles[CHILD_HANDLE], timeout);            if (rv == WAIT_OBJECT_0) {                ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf,                             "Parent: Child process exited successfully.");                CloseHandle(event_handles[CHILD_HANDLE]);                event_handles[CHILD_HANDLE] = NULL;            }            else {                ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf,                             "Parent: Forcing termination of child process %d ", event_handles[CHILD_HANDLE]);                TerminateProcess(event_handles[CHILD_HANDLE], 1);                CloseHandle(event_handles[CHILD_HANDLE]);                event_handles[CHILD_HANDLE] = NULL;            }        }        return 0;  /* Tell the caller we do not want to restart */    }    winnt_mpm_state = AP_MPMQ_STARTING;    return 1;      /* Tell the caller we want a restart */}/* service_nt_main_fn needs to append the StartService() args  * outside of our call stack and thread as the service starts... */apr_array_header_t *mpm_new_argv;/* Remember service_to_start failures to log and fail in pre_config. * Remember inst_argc and inst_argv for installing or starting the * service after we preflight the config. */AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result){    switch(query_code){        case AP_MPMQ_MAX_DAEMON_USED:            *result = MAXIMUM_WAIT_OBJECTS;            return APR_SUCCESS;        case AP_MPMQ_IS_THREADED:            *result = AP_MPMQ_STATIC;            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 = thread_limit;            return APR_SUCCESS;        case AP_MPMQ_MAX_THREADS:            *result = ap_threads_per_child;            return APR_SUCCESS;        case AP_MPMQ_MIN_SPARE_DAEMONS:            *result = 0;            return APR_SUCCESS;        case AP_MPMQ_MIN_SPARE_THREADS:                *result = 0;            return APR_SUCCESS;        case AP_MPMQ_MAX_SPARE_DAEMONS:            *result = 0;            return APR_SUCCESS;        case AP_MPMQ_MAX_SPARE_THREADS:            *result = 0;            return APR_SUCCESS;        case AP_MPMQ_MAX_REQUESTS_DAEMON:            *result = ap_max_requests_per_child;            return APR_SUCCESS;        case AP_MPMQ_MAX_DAEMONS:            *result = 0;            return APR_SUCCESS;        case AP_MPMQ_MPM_STATE:            *result = winnt_mpm_state;            return APR_SUCCESS;    }    return APR_ENOTIMPL;} #define SERVICE_UNSET (-1)static apr_status_t service_set = SERVICE_UNSET;static apr_status_t service_to_start_success;static int inst_argc;static const char * const *inst_argv;static char *service_name = NULL;    void winnt_rewrite_args(process_rec *process) {    /* Handle the following SCM aspects in this phase:     *     *   -k runservice [transition for WinNT, nothing for Win9x]     *   -k (!)install [error out if name is not installed]     *   -k uninstall     *   -k stop     *   -k shutdown (same as -k stop). Maintained for backward compatability.     *     * We can't leave this phase until we know our identity     * and modify the command arguments appropriately.     *     * We do not care if the .conf file exists or is parsable when     * attempting to stop or uninstall a service.     */    apr_status_t rv;    char *def_server_root;    char *binpath;    char optbuf[3];    const char *optarg;    int fixed_args;    char *pid;    apr_getopt_t *opt;    int running_as_service = 1;    int errout = 0;    pconf = process->pconf;    osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);    GetVersionEx(&osver);    /* AP_PARENT_PID is only valid in the child */    pid = getenv("AP_PARENT_PID");    if (pid)     {        /* This is the child */        my_pid = GetCurrentProcessId();        parent_pid = (DWORD) atol(pid);        /* Prevent holding open the (nonexistant) console */        real_exit_code = 0;        /* The parent is responsible for providing the         * COMPLETE ARGUMENTS REQUIRED to the child.         *         * No further argument parsing is needed, but         * for good measure we will provide a simple         * signal string for later testing.         */        signal_arg = "runchild";        return;    }        /* This is the parent, we have a long way to go :-) */    parent_pid = my_pid = GetCurrentProcessId();    /* This behavior is voided by setting real_exit_code to 0 */    atexit(hold_console_open_on_error);    /* Rewrite process->argv[];      *     * strip out -k signal into signal_arg     * strip out -n servicename and set the names     * add default -d serverroot from the path of this executable     *      * The end result will look like:     *     * The invocation command (%0)     *     The -d serverroot default from the running executable     *         The requested service's (-n) registry ConfigArgs     *             The WinNT SCM's StartService() args     */    if ((rv = ap_os_proc_filepath(&binpath, process->pconf))            != APR_SUCCESS) {        ap_log_error(APLOG_MARK,APLOG_CRIT, rv, NULL,                      "Failed to get the full path of %s", process->argv[0]);        exit(APEXIT_INIT);    }    /* WARNING: There is an implict assumption here that the     * executable resides in ServerRoot or ServerRoot\bin     */    def_server_root = (char *) apr_filename_of_pathname(binpath);    if (def_server_root > binpath) {        *(def_server_root - 1) = '\0';        def_server_root = (char *) apr_filename_of_pathname(binpath);        if (!strcasecmp(def_server_root, "bin"))            *(def_server_root - 1) = '\0';    }    apr_filepath_merge(&def_server_root, NULL, binpath,                        APR_FILEPATH_TRUENAME, process->pool);    /* Use process->pool so that the rewritten argv     * lasts for the lifetime of the server process,     * because pconf will be destroyed after the      * initial pre-flight of the config parser.     */    mpm_new_argv = apr_array_make(process->pool, process->argc + 2,                                  sizeof(const char *));    *(const char **)apr_array_push(mpm_new_argv) = process->argv[0];    *(const char **)apr_array_push(mpm_new_argv) = "-d";    *(const char **)apr_array_push(mpm_new_argv) = def_server_root;    fixed_args = mpm_new_argv->nelts;    optbuf[0] = '-';    optbuf[2] = '\0';    apr_getopt_init(&opt, process->pool, process->argc, (char**) process->argv);    opt->errfn = NULL;    while ((rv = apr_getopt(opt, "wn:k:" AP_SERVER_BASEARGS,                             optbuf + 1, &optarg)) == APR_SUCCESS) {        switch (optbuf[1]) {        /* Shortcuts; include the -w option to hold the window open on error.         * This must not be toggled once we reset real_exit_code to 0!         */        case 'w':            if (real_exit_code)                real_exit_code = 2;            break;        case 'n':            service_set = mpm_service_set_name(process->pool, &service_name,                                                optarg);            break;        case 'k':            signal_arg = optarg;            break;        case 'E':            errout = 1;            /* Fall through so the Apache main() handles the 'E' arg */        default:            *(const char **)apr_array_push(mpm_new_argv) =                apr_pstrdup(process->pool, optbuf);            if (optarg) {                *(const char **)apr_array_push(mpm_new_argv) = optarg;            }            break;        }    }        /* back up to capture the bad argument */    if (rv == APR_BADCH || rv == APR_BADARG) {        opt->ind--;    }    while (opt->ind < opt->argc) {        *(const char **)apr_array_push(mpm_new_argv) =            apr_pstrdup(process->pool, opt->argv[opt->ind++]);    }    /* Track the number of args actually entered by the user */    inst_argc = mpm_new_argv->nelts - fixed_args;    /* Provide a default 'run' -k arg to simplify signal_arg tests */    if (!signal_arg)    {        signal_arg = "run";        running_as_service = 0;    }    if (!strcasecmp(signal_arg, "runservice"))     {        /* Start the NT Service _NOW_ because the WinNT SCM is          * expecting us to rapidly assume control of our own          * process, the SCM will tell us our service name, and         * may have extra StartService() command arguments to         * add for us.         *         * The SCM will generally invoke the executable with         * the c:\win\system32 default directory.  This is very         * lethal if folks use ServerRoot /foopath on windows         * without a drive letter.  Change to the default root         * (path to apache root, above /bin) for safety.         */        apr_filepath_set(def_server_root, process->pool);                /* Any other process has a console, so we don't to begin         * a Win9x service until the configuration is parsed and         * any command line errors are reported.         *         * We hold the return value so that we can die in pre_config         * after logging begins, and the failure can land in the log.         */        if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)         {            if (!errout) {                mpm_nt_eventlog_stderr_open(service_name, process->pool);            }            service_to_start_success = mpm_service_to_start(&service_name,                                                            process->pool);            if (service_to_start_success == APR_SUCCESS) {

⌨️ 快捷键说明

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