From: Jeff Trawick Date: Thu, 23 May 2002 12:58:37 +0000 (+0000) Subject: Add "-k start|startssl|restart|graceful|stop" support to httpd X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e2bd3d5aaaaa0fcfc5bd4cd77fa0022799203a16;p=apache Add "-k start|startssl|restart|graceful|stop" support to httpd for the Unix MPMs. These have semantics very similar to the old apachectl commands of the same name. The use of stderr/stdout and exit status for error conditions needs to be revisited. For now it matches apachectl behavior. Justin Erenkrantz got the ball rolling with this feature. Some of his support code was used unchanged. Other code was shuffled around and modified or rewritten. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@95237 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 48399aa3a6..62e1aedae4 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,10 @@ Changes with Apache 2.0.37 + *) Add "-k start|startssl|restart|graceful|stop" support to httpd + for the Unix MPMs. These have semantics very similar to the + old apachectl commands of the same name. + [Justin Erenkrantz, Jeff Trawick] + *) Make sure that the runtime dir is created by make install. PR 9233. [Jeff Trawick] diff --git a/include/http_main.h b/include/http_main.h index 724f5575b4..46c322acc7 100644 --- a/include/http_main.h +++ b/include/http_main.h @@ -59,6 +59,8 @@ #ifndef APACHE_HTTP_MAIN_H #define APACHE_HTTP_MAIN_H +#include "apr_optional.h" + /* AP_SERVER_BASEARGS is the command argument list parsed by http_main.c * in apr_getopt() format. Use this for default'ing args that the MPM * can safely ignore and pass on from its rewrite_args() handler. @@ -89,6 +91,8 @@ AP_DECLARE_DATA extern apr_array_header_t *ap_server_post_read_config; * effect the server based on command line options */ AP_DECLARE_DATA extern apr_array_header_t *ap_server_config_defines; +APR_DECLARE_OPTIONAL_FN(int, ap_signal_server, (int *, apr_pool_t *)); + #ifdef __cplusplus } #endif diff --git a/include/mpm_common.h b/include/mpm_common.h index 472f9b5928..be58aec4a4 100644 --- a/include/mpm_common.h +++ b/include/mpm_common.h @@ -280,6 +280,11 @@ const char *ap_mpm_set_coredumpdir(cmd_parms *cmd, void *dummy, const char *arg); #endif +#ifdef AP_MPM_WANT_SIGNAL_SERVER +int ap_signal_server(int *, apr_pool_t *); +void ap_mpm_rewrite_args(process_rec *); +#endif + #ifdef __cplusplus } #endif diff --git a/server/main.c b/server/main.c index 49a85f94d3..9a1cdb456c 100644 --- a/server/main.c +++ b/server/main.c @@ -76,6 +76,7 @@ #include "apr_uri.h" #include "util_ebcdic.h" #include "ap_mpm.h" +#include "mpm_common.h" /* WARNING: Win32 binds http_main.c dynamically to the server. Please place * extern functions and global data in another appropriate module. @@ -309,7 +310,11 @@ static void usage(process_rec *process) " %s [-k install|config|uninstall] [-n service_name]", pad); #endif - +#ifdef AP_MPM_WANT_SIGNAL_SERVER + ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, + " %s [-k start|startssl|restart|graceful|stop]", + pad); +#endif ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, " %s [-v] [-V] [-h] [-l] [-L] [-t] [-T]", pad); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, @@ -404,6 +409,7 @@ int main(int argc, const char * const argv[]) apr_status_t rv; module **mod; const char *optarg; + APR_OPTIONAL_FN_TYPE(ap_signal_server) *signal_server; AP_MONCONTROL(0); /* turn off profiling of startup */ @@ -565,6 +571,15 @@ int main(int argc, const char * const argv[]) destroy_and_exit_process(process, 0); } + signal_server = APR_RETRIEVE_OPTIONAL_FN(ap_signal_server); + if (signal_server) { + int exit_status; + + if (signal_server(&exit_status, pconf) != 0) { + destroy_and_exit_process(process, exit_status); + } + } + apr_pool_clear(plog); /* It is assumed that if you are going to fail the open_logs phase, then diff --git a/server/mpm/prefork/mpm.h b/server/mpm/prefork/mpm.h index 514c2b02f4..fc2ff771c5 100644 --- a/server/mpm/prefork/mpm.h +++ b/server/mpm/prefork/mpm.h @@ -77,6 +77,7 @@ #define AP_MPM_WANT_SET_MAX_REQUESTS #define AP_MPM_WANT_SET_COREDUMPDIR #define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH +#define AP_MPM_WANT_SIGNAL_SERVER #define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK #define AP_MPM_USES_POD 1 diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c index adb3aae129..1f5f7a0d24 100644 --- a/server/mpm/prefork/prefork.c +++ b/server/mpm/prefork/prefork.c @@ -1388,7 +1388,7 @@ AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF, module AP_MODULE_DECLARE_DATA mpm_prefork_module = { MPM20_MODULE_STUFF, - NULL, /* hook to run before apache parses args */ + ap_mpm_rewrite_args, /* hook to run before apache parses args */ NULL, /* create per-directory config structure */ NULL, /* merge per-directory config structures */ NULL, /* create per-server config structure */ diff --git a/server/mpm/worker/mpm.h b/server/mpm/worker/mpm.h index 896fb82b96..a22c8f0686 100644 --- a/server/mpm/worker/mpm.h +++ b/server/mpm/worker/mpm.h @@ -74,6 +74,7 @@ #define AP_MPM_WANT_SET_MAX_REQUESTS #define AP_MPM_WANT_SET_COREDUMPDIR #define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH +#define AP_MPM_WANT_SIGNAL_SERVER #define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid) diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c index 913273e56c..f9c23ca270 100644 --- a/server/mpm/worker/worker.c +++ b/server/mpm/worker/worker.c @@ -2158,7 +2158,7 @@ AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF, module AP_MODULE_DECLARE_DATA mpm_worker_module = { MPM20_MODULE_STUFF, - NULL, /* hook to run before apache parses args */ + ap_mpm_rewrite_args, /* hook to run before apache parses args */ NULL, /* create per-directory config structure */ NULL, /* merge per-directory config structures */ NULL, /* create per-server config structure */ diff --git a/server/mpm_common.c b/server/mpm_common.c index fd1f3dd394..c6d4e9524c 100644 --- a/server/mpm_common.c +++ b/server/mpm_common.c @@ -73,6 +73,8 @@ #include "apr_strings.h" #define APR_WANT_STRFUNC #include "apr_want.h" +#include "apr_getopt.h" +#include "apr_optional.h" #include "httpd.h" #include "http_config.h" @@ -730,3 +732,157 @@ AP_DECLARE(const char *) ap_mpm_set_accept_lock_mech(cmd_parms *cmd, } #endif + +#ifdef AP_MPM_WANT_SIGNAL_SERVER + +static const char *dash_k_arg; + +static int send_signal(pid_t pid, int sig) +{ + if (kill(pid, sig) < 0) { + ap_log_error(APLOG_MARK, APLOG_STARTUP, errno, NULL, + "sending signal to server"); + return 1; + } + return 0; +} + +int ap_signal_server(int *exit_status, apr_pool_t *pconf) +{ + apr_status_t rv; + pid_t otherpid; + int running = 0; + int have_pid_file = 0; + const char *status; + + *exit_status = 0; + + rv = ap_read_pid(pconf, ap_pid_fname, &otherpid); + if (rv != APR_SUCCESS) { + if (rv != APR_ENOENT) { + ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, NULL, + "Error retrieving pid file %s", ap_pid_fname); + *exit_status = 1; + return 1; + } + status = "httpd (no pid file) not running"; + } + else { + have_pid_file = 1; + if (kill(otherpid, 0) == 0) { + running = 1; + status = apr_psprintf(pconf, + "httpd (pid %" APR_PID_T_FMT ") already " + "running", otherpid); + } + else { + status = apr_psprintf(pconf, + "httpd (pid %" APR_PID_T_FMT "?) not running", + otherpid); + } + } + + if (!strcmp(dash_k_arg, "start")) { + if (running) { + printf("%s\n", status); + return 1; + } + } + + if (!strcmp(dash_k_arg, "stop")) { + if (!running) { + printf("%s\n", status); + } + else { + send_signal(otherpid, SIGTERM); + } + return 1; + } + + if (!strcmp(dash_k_arg, "restart")) { + if (!running) { + printf("httpd not running, trying to start\n"); + } + else { + *exit_status = send_signal(otherpid, SIGHUP); + return 1; + } + } + + if (!strcmp(dash_k_arg, "graceful")) { + if (!running) { + printf("httpd not running, trying to start\n"); + } + else { + *exit_status = send_signal(otherpid, SIGUSR1); + return 1; + } + } + + return 0; +} + +void ap_mpm_rewrite_args(process_rec *process) +{ + apr_array_header_t *mpm_new_argv; + apr_status_t rv; + apr_getopt_t *opt; + char optbuf[3]; + const char *optarg; + int fixed_args; + + mpm_new_argv = apr_array_make(process->pool, process->argc, + sizeof(const char **)); + *(const char **)apr_array_push(mpm_new_argv) = process->argv[0]; + fixed_args = mpm_new_argv->nelts; + apr_getopt_init(&opt, process->pool, process->argc, process->argv); + opt->errfn = NULL; + optbuf[0] = '-'; + while ((rv = apr_getopt(opt, "k:" AP_SERVER_BASEARGS, + optbuf + 1, &optarg)) == APR_SUCCESS) { + switch(optbuf[1]) { + case 'k': + if (!dash_k_arg) { + if (!strcmp(optarg, "start") || !strcmp(optarg, "stop") || + !strcmp(optarg, "restart") || !strcmp(optarg, "graceful")) { + dash_k_arg = optarg; + break; + } + if (!strcmp(optarg, "startssl")) { + char **new_define; + + dash_k_arg = "start"; + new_define = (char **)apr_array_push(ap_server_config_defines); + *new_define = "SSL"; + 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; + } + } + } + + /* 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++]); + } + + process->argc = mpm_new_argv->nelts; + process->argv = (const char * const *)mpm_new_argv->elts; + + if (dash_k_arg) { + APR_REGISTER_OPTIONAL_FN(ap_signal_server); + } +} + +#endif /* AP_MPM_WANT_SIGNAL_SERVER */ +