Under Cygwin, the apparent method to run a service is using
cygrunsrv.exe. Unfortunately cygrunsrv's method of detecting if the
service stayed running or not is based on whether the process that it
spawned is still running or not.
The patch below adds an option -W (cygwin only) that modifies the
behavior of detach(). With this patch, httpd -W will keep an httpd
process running just waiting for httpd to exit or for it to be signalled
by cygrunsrv to shut down the service.
The only other behavior change that is introduced is SIGUSR2 is now
caught and ignored. This is used to work around an apparent bug in
cygwin's waitpid() when the child process dies in a non-graceful way
(kill -9).
I welcome all comments.
Mike
Index: main/http_main.c
===
RCS file: /home/cvspublic/apache-1.3/src/main/http_main.c,v
retrieving revision 1.576
diff -c -r1.576 http_main.c
*** main/http_main.c26 Feb 2002 15:04:53 - 1.576
--- main/http_main.c27 Feb 2002 21:31:28 -
***
*** 341,346
--- 341,357
static int one_process = 0;
+ /* parent_wait --- when running as a service under Cygwin, the first process
+ * should not die else cygrunsrv thinks that httpd has died when in reality it
+ * has just gone into the background. When parent_wait is non-zero
+ * (-W option, compiled under Cygnus only) the parent sits around just
+ * waiting for its first child to die.
+ */
+
+ #if defined(CYGWIN)
+ static int parent_wait = 0;
+ #endif
+
/* set if timeouts are to be handled by the children and not by the parent.
* i.e. child_timeouts = !standalone || one_process.
*/
***
*** 396,401
--- 407,434
/* Global, alas, so http_core can talk to us */
enum server_token_type ap_server_tokens = SrvTk_FULL;
+ /* parentwait_pid --- contains the PID of the master httpd so that kill
+ * signals sent from cygrunsrv to httpd can be delivered to the master
+ * httpd. Only used when compiled under Cygnus and the -W runtime flag
+ * is used.
+ */
+ #if defined(CYGWIN)
+ static pid_t parentwait_pid;
+ #endif
+
+ /*
+ * This is a signal handler that passes signals on from cygrunsrv to the
+ * master httpd.. Only used when compiled under Cygnus and the -W
+ * runtime flag is used.
+ */
+ #if defined(CYGWIN)
+ static void parentwait_kill(int signum) {
+ printf("Caught signal %d and passing it on to pid %d\n",
+ parentwait_pid, signum);
+ kill(parentwait_pid, signum);
+ }
+ #endif
+
/*
* This routine is called when the pconf pool is vacuumed. It resets the
* server version string to a known value and [re]enables modifications
***
*** 1358,1363
--- 1391,1399
#endif
fprintf(stderr, " %s [-C \"directive\"] [-c \"directive\"]\n", pad);
fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t] [-T]\n", pad);
+ #if defined(CYGWIN)
+ fprintf(stderr, " %s [-W]\n", pad);
+ #endif
fprintf(stderr, "Options:\n");
#ifdef SHARED_CORE
fprintf(stderr, " -R directory : specify an alternate location for shared
object files\n");
***
*** 1389,1394
--- 1425,1434
fprintf(stderr, " -k uninstall | -u: uninstall an Apache service\n");
fprintf(stderr, " -W service : after -k config|install; Apache starts
after 'service'\n");
fprintf(stderr, " -w : holds the window open for 30 seconds for
fatal errors.\n");
+ #else /* !WIN32 */
+ #if defined(CYGWIN)
+ fprintf(stderr, " -W : one process just waits for signals from
+cygrunsrv\n");
+ #endif
#endif
#if defined(NETWARE)
***
*** 3369,3376
!defined(BONE)
/* Don't detach for MPE because child processes can't survive the death of
the parent. */
! if ((x = fork()) > 0)
exit(0);
else if (x == -1) {
perror("fork");
fprintf(stderr, "%s: unable to fork new process\n", ap_server_argv0);
--- 3409,3469
!defined(BONE)
/* Don't detach for MPE because child processes can't survive the death of
the parent. */
! #if defined(CYGWIN)
! if ( parent_wait ) {
! signal(SIGUSR2, SIG_IGN);
! }
! #endif
! if ((x = fork()) > 0) {
! #if defined(CYGWIN)
! int status, exitval = 0;
! if ( parent_wait == 0 ) {
! exit(0);
! }
! parentwait_pid = x;
! signal(SIGHUP, parentwait_kill);
! signal(SIGINT, parentwait_kill);
! signal(SIGQUIT, parentwait_kill);
! signal(SIGTERM, parentwait_kill);
! while ( 1 ) {
! waitpid(x, &status, WNOHANG);
! if ( WIFEXITED(status) ) {
! exitval = WEXITSTATUS(status);
! printf("Child pid %d exited with status %d\n", x, exitval);
! if ( WIFSIGNALED(status) ) {
! printf("Child pid %d received signal %d\n", x,
!