📄 mpm_winnt.c
字号:
mpm_service_stopping(); } /* Signal each child processes to die */ for (i = 0; i < current_live_processes; i++) { printf("SetEvent handle = %d\n", process_kill_events[i]); if (SetEvent(process_kill_events[i]) == 0) ap_log_error(APLOG_MARK,APLOG_ERR, apr_get_os_error(), server_conf, "master_main: SetEvent for child process in slot #%d failed", i); } while (current_live_processes && ((tmstart+60) > time(NULL))) { rv = WaitForMultipleObjects(current_live_processes, (HANDLE *)process_handles, FALSE, 2000); if (rv == WAIT_TIMEOUT) continue; ap_assert(rv != WAIT_FAILED); cld = rv - WAIT_OBJECT_0; ap_assert(rv < current_live_processes); cleanup_process(process_handles, process_kill_events, cld, ¤t_live_processes); } for (i = 0; i < current_live_processes; i++) { ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO, APR_SUCCESS, server_conf, "Parent: Forcing termination of child #%d (handle %d)", i, process_handles[i]); TerminateProcess((HANDLE) process_handles[i], 1); } return 0; /* Tell the caller we do not want to restart */ } return 1; /* Tell the caller we want a restart */}#define SERVICE_UNNAMED (-1)/* 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_DAEMONS: *result = MAXIMUM_WAIT_OBJECTS; return APR_SUCCESS; case AP_MPMQ_IS_THREADED: *result = 1; return APR_SUCCESS; case AP_MPMQ_IS_FORKED: *result = 0; return APR_SUCCESS; } return APR_ENOTIMPL;} static apr_status_t service_to_start_success;static int inst_argc;static const char * const *inst_argv; 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] * * We can't leave this phase until we know our identity * and modify the command arguments appropriately. */ apr_status_t service_named = SERVICE_UNNAMED; apr_status_t rv; char *def_server_root; char fnbuf[MAX_PATH]; char optbuf[3]; const char *optarg; int fixed_args; char *pid; apr_getopt_t *opt; int running_as_service = 1; 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); /* 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(); /* Rewrite process->argv[]; * * strip out -k signal into signal_arg * strip out -n servicename into service_name & display_name * 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 (!GetModuleFileName(NULL, fnbuf, sizeof(fnbuf))) { rv = apr_get_os_error(); ap_log_error(APLOG_MARK,APLOG_ERR, rv, NULL, "Failed to get the path of Apache.exe"); exit(1); } /* WARNING: There is an implict assumption here that the * executable resides in ServerRoot or ServerRoot\bin */ def_server_root = (char *) apr_filename_of_pathname(fnbuf); if (def_server_root > fnbuf) { *(def_server_root - 1) = '\0'; def_server_root = (char *) apr_filename_of_pathname(fnbuf); if (!strcasecmp(def_server_root, "bin")) *(def_server_root - 1) = '\0'; } def_server_root = ap_os_canonical_filename(process->pool, fnbuf); /* 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); while (apr_getopt(opt, "n:k:iu" AP_SERVER_BASEARGS, optbuf + 1, &optarg) == APR_SUCCESS) { switch (optbuf[1]) { case 'n': service_named = mpm_service_set_name(process->pool, optarg); break; case 'k': signal_arg = optarg; break; case 'i': ap_log_error(APLOG_MARK,APLOG_WARNING, 0, NULL, "-i is deprecated. Use -k install."); signal_arg = "install"; break; case 'u': ap_log_error(APLOG_MARK,APLOG_WARNING, 0, NULL, "-u is deprecated. Use -k uninstall."); signal_arg = "uninstall"; break; 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; } } /* 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. * * 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) { service_to_start_success = mpm_service_to_start(); if (service_to_start_success == APR_SUCCESS) service_named = APR_SUCCESS; } } if (service_named == SERVICE_UNNAMED && running_as_service) { service_named = mpm_service_set_name(process->pool, DEFAULT_SERVICE_NAME); } if (!strcasecmp(signal_arg, "install")) /* -k install */ { if (service_named == APR_SUCCESS) { ap_log_error(APLOG_MARK,APLOG_ERR, 0, NULL, "%s: Service is already installed.", display_name); exit(1); } } else if (running_as_service) { if (service_named == APR_SUCCESS) { rv = mpm_merge_service_args(process->pool, mpm_new_argv, fixed_args); if (rv == APR_SUCCESS) { ap_log_error(APLOG_MARK,APLOG_NOERRNO|APLOG_INFO, 0, NULL, "Using ConfigArgs of the installed service " "\"%s\".", display_name); } else { ap_log_error(APLOG_MARK,APLOG_INFO, rv, NULL, "No installed ConfigArgs for the service " "\"%s\", using Apache defaults.", display_name); } } else { ap_log_error(APLOG_MARK,APLOG_INFO|APLOG_NOERRNO, 0, NULL, "No installed service named \"%s\".", display_name); exit(1); } } /* Track the args actually entered by the user. * These will be used for the -k install parameters, as well as * for the -k start service override arguments. */ inst_argv = (const char * const *)mpm_new_argv->elts + mpm_new_argv->nelts - inst_argc; process->argc = mpm_new_argv->nelts; process->argv = (const char * const *) mpm_new_argv->elts;}static void winnt_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp) { /* Handle the following SCM aspects in this phase: * * -k runservice [WinNT errors logged from rewrite_args] * -k uninstall * -k stop * * in these cases we -don't- care if httpd.conf has config errors! */ apr_status_t rv; if (ap_exists_config_define("ONE_PROCESS")) one_process = -1; if (ap_exists_config_define("ONE_PROCESS")) one_process = -1; if (!strcasecmp(signal_arg, "runservice") && (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (service_to_start_success != APR_SUCCESS)) { ap_log_error(APLOG_MARK,APLOG_ERR, service_to_start_success, NULL, "%s: Unable to start the service manager.", display_name); exit(1); } if (!strcasecmp(signal_arg, "uninstall")) { rv = mpm_service_uninstall(); exit(rv); } if (!strcasecmp(signal_arg, "stop")) { mpm_signal_service(ptemp, 0); exit(0); } ap_listen_pre_config(); ap_daemons_to_start = DEFAULT_NUM_DAEMON; ap_threads_per_child = DEFAULT_START_THREAD; ap_pid_fname = DEFAULT_PIDLOG; ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD; apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));}static void winnt_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec* server){ static int restart_num = 0; apr_status_t rv = 0; server_conf = server; /* Handle the following SCM aspects in this phase: * * -k install * -k start * -k restart * -k runservice [Win95, only once - after we parsed the config] * * because all of these signals are useful _only_ if there * is a valid conf\httpd.conf environment to start. * * We reached this phase by avoiding errors that would cause * these options to fail unexpectedly in another process. */ if (!strcasecmp(signal_arg, "install")) { rv = mpm_service_install(ptemp, inst_argc, inst_argv); exit (rv); } if (!strcasecmp(signal_arg, "start")) { rv = mpm_service_start(ptemp, inst_argc, inst_argv); exit (rv); } if (!strcasecmp(signal_arg, "restart")) { mpm_signal_service(ptemp, 1); exit (rv); } if (parent_pid == my_pid) { if (restart_num++ == 1) { /* This code should be run once in the parent and not run * across a restart */ PSECURITY_ATTRIBUTES sa = GetNullACL(); /* returns NULL if invalid (Win95?) */ setup_signal_names(apr_psprintf(pconf,"ap%d", parent_pid)); ap_log_pid(pconf, ap_pid_fname); /* Create shutdown event, apPID_shutdown, where PID is the parent * Apache process ID. Shutdown is signaled by 'apache -k shutdown'. */ shutdown_event = CreateEvent(sa, FALSE, FALSE, signal_shutdown_name); if (!shutdown_e
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -