Here is another pass at it, starting with some of Justin's code but
trying to work out a more agreeable place for some of the function.
This puts the -k parsing in a rewrite_args hook (one for the Unix MPMs
is implemented in mpm_common.c) and puts the actual signalling code in
an optional function called from main() (again, one for the Unix MPMs
is implemented in mpm_common.c).
This patch concentrates on distributing the work to the right places.
It only implements "-k stop", it is only enabled for the prefork MPM
(easy to enable for other MPMs), and I didn't sort out the httpd help
text (gross).
Hopefully this won't break anybody, and it can be quickly filled in
with the necessary details.
Any comments/concerns? There must be at least ten improvements to
this that different people can think of :)
Index: include/http_log.h
===================================================================
RCS file: /home/cvs/httpd-2.0/include/http_log.h,v
retrieving revision 1.36
diff -u -r1.36 http_log.h
--- include/http_log.h 17 May 2002 10:48:06 -0000 1.36
+++ include/http_log.h 22 May 2002 17:36:39 -0000
@@ -240,6 +240,14 @@
*/
AP_DECLARE(void) ap_log_pid(apr_pool_t *p, const char *fname);
+/**
+ * Retrieve the pid from a pidfile.
+ * @param p The pool to use for logging
+ * @param filename The name of the file containing the pid
+ * @param mypid Pointer to pid_t (valid only if return APR_SUCCESS)
+ */
+AP_DECLARE(apr_status_t) ap_read_pid(apr_pool_t *p, const char *filename, pid_t
+*mypid);
+
typedef struct piped_log piped_log;
/**
Index: include/http_main.h
===================================================================
RCS file: /home/cvs/httpd-2.0/include/http_main.h,v
retrieving revision 1.23
diff -u -r1.23 http_main.h
--- include/http_main.h 17 Apr 2002 16:36:27 -0000 1.23
+++ include/http_main.h 22 May 2002 17:36:39 -0000
@@ -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.
@@ -88,6 +90,8 @@
/** An array of all -D defines on the command line. This allows people to
* 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
}
Index: include/mpm_common.h
===================================================================
RCS file: /home/cvs/httpd-2.0/include/mpm_common.h,v
retrieving revision 1.36
diff -u -r1.36 mpm_common.h
--- include/mpm_common.h 29 Mar 2002 16:21:48 -0000 1.36
+++ include/mpm_common.h 22 May 2002 17:36:39 -0000
@@ -280,6 +280,11 @@
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
Index: server/log.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/log.c,v
retrieving revision 1.120
diff -u -r1.120 log.c
--- server/log.c 17 May 2002 11:11:37 -0000 1.120
+++ server/log.c 22 May 2002 17:36:39 -0000
@@ -626,6 +626,55 @@
saved_pid = mypid;
}
+AP_DECLARE(apr_status_t) ap_read_pid(apr_pool_t *p, const char *filename,
+ pid_t *mypid)
+{
+ const int BUFFER_SIZE = sizeof(long) * 3 + 2; /* see apr_ltoa */
+ apr_file_t *pid_file = NULL;
+ apr_status_t rv;
+ const char *fname;
+ char *buf, *endptr;
+ apr_size_t bytes_wanted, bytes_read;
+
+ if (!filename) {
+ return APR_EGENERAL;
+ }
+
+ fname = ap_server_root_relative(p, filename);
+ if (!fname) {
+ ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, APR_EBADPATH,
+ NULL, "Invalid PID file path %s, ignoring.", filename);
+ return APR_EGENERAL;
+ }
+
+ rv = apr_file_open(&pid_file, fname, APR_READ, APR_OS_DEFAULT, p);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ bytes_wanted = BUFFER_SIZE;
+ endptr = buf = apr_palloc(p, BUFFER_SIZE);
+ do {
+ bytes_read = bytes_wanted;
+ rv = apr_file_read(pid_file, endptr, &bytes_read);
+ if (rv != APR_SUCCESS && rv != APR_EOF) {
+ return rv;
+ }
+ bytes_wanted -= bytes_read;
+ endptr += bytes_read;
+ }
+ while (bytes_wanted > 0 && rv != APR_EOF);
+
+ *mypid = strtol(buf, &endptr, 10);
+ /* We only know for sure that the beginning part is the pid. */
+ if (*buf == '\0' || *endptr != '\n') {
+ return APR_EGENERAL;
+ }
+
+ apr_file_close(pid_file);
+ return APR_SUCCESS;
+}
+
AP_DECLARE(void) ap_log_assert(const char *szExp, const char *szFile,
int nLine)
{
Index: server/main.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/main.c,v
retrieving revision 1.129
diff -u -r1.129 main.c
--- server/main.c 21 May 2002 15:40:51 -0000 1.129
+++ server/main.c 22 May 2002 17:36:39 -0000
@@ -404,8 +404,9 @@
apr_status_t rv;
module **mod;
const char *optarg;
+ APR_OPTIONAL_FN_TYPE(ap_signal_server) *signal_server;
- AP_MONCONTROL(0); /* turn of profiling of startup */
+ AP_MONCONTROL(0); /* turn off profiling of startup */
apr_app_initialize(&argc, &argv, NULL);
@@ -563,6 +564,15 @@
if (configtestonly) {
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "Syntax OK");
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);
Index: server/mpm_common.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/mpm_common.c,v
retrieving revision 1.94
diff -u -r1.94 mpm_common.c
--- server/mpm_common.c 17 May 2002 11:11:37 -0000 1.94
+++ server/mpm_common.c 22 May 2002 17:36:39 -0000
@@ -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,87 @@
}
#endif
+
+#ifdef AP_MPM_WANT_SIGNAL_SERVER
+
+static const char *dash_k_arg;
+
+int ap_signal_server(int *exit_status, apr_pool_t *pconf)
+{
+ apr_status_t rv;
+ pid_t otherpid;
+
+ rv = ap_read_pid(pconf, ap_pid_fname, &otherpid);
+ if (rv != APR_SUCCESS && 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;
+ }
+
+ if (!strcmp(dash_k_arg, "stop")) {
+ if (rv != APR_SUCCESS) {
+ printf("httpd (no pid file) not running\n");
+ }
+ else {
+ kill(otherpid, SIGTERM);
+ }
+ *exit_status = 0;
+ 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 && !strcmp(optarg, "stop")) {
+ dash_k_arg = optarg;
+ 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 */
+
Index: server/mpm/prefork/mpm.h
===================================================================
RCS file: /home/cvs/httpd-2.0/server/mpm/prefork/mpm.h,v
retrieving revision 1.19
diff -u -r1.19 mpm.h
--- server/mpm/prefork/mpm.h 29 Mar 2002 16:15:33 -0000 1.19
+++ server/mpm/prefork/mpm.h 22 May 2002 17:36:39 -0000
@@ -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
Index: server/mpm/prefork/prefork.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/mpm/prefork/prefork.c,v
retrieving revision 1.263
diff -u -r1.263 prefork.c
--- server/mpm/prefork/prefork.c 17 May 2002 11:11:39 -0000 1.263
+++ server/mpm/prefork/prefork.c 22 May 2002 17:36:39 -0000
@@ -1388,7 +1388,7 @@
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 */
--
Jeff Trawick | [EMAIL PROTECTED]
Born in Roswell... married an alien...