delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin-apps/2001/06/15/16:02:00

Mailing-List: contact cygwin-apps-help AT sourceware DOT cygnus DOT com; run by ezmlm
Sender: cygwin-apps-owner AT sourceware DOT cygnus DOT com
List-Subscribe: <mailto:cygwin-apps-subscribe AT sources DOT redhat DOT com>
List-Archive: <http://sources.redhat.com/ml/cygwin-apps/>
List-Post: <mailto:cygwin-apps AT sources DOT redhat DOT com>
List-Help: <mailto:cygwin-apps-help AT sources DOT redhat DOT com>, <http://sources.redhat.com/lists.html#faqs>
Delivered-To: mailing list cygwin-apps AT sources DOT redhat DOT com
Message-ID: <3B2A666C.932B5FB7@ontosys.com>
Date: Fri, 15 Jun 2001 14:47:56 -0500
From: Fred Yankowski <fcy AT ontosys DOT com>
X-Mailer: Mozilla 4.76 [en] (WinNT; U)
X-Accept-Language: en
MIME-Version: 1.0
To: cygwin-apps AT cygwin DOT com
Cc: pgsql-cygwin AT postgresql DOT org
Subject: cygrunsrv patch for system shutdown handling
References: <20010517161408 DOT A60686 AT enteract DOT com> <20010518101617 DOT B31266 AT cygbert DOT vinschen DOT de> <20010518103001 DOT A61059 AT enteract DOT com> <20010518182956 DOT D31266 AT cygbert DOT vinschen DOT de>

This is a multi-part message in MIME format.
--------------4B8487E3562AF76A6AD717ED
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Attached is a patch to cygrunsrv that adds an optional feature where
cygrunsrv accepts SERVICE_CONTROL_SHUTDOWN notifications from the
Service Control Manager and explicitly terminates the managed
application process on receipt of such a notification.  This gives the
application a chance to shutdown cleanly, just as it does during a
manual stop ("net stop").

This feature is useful with the Cygwin port of PostgreSQL.  Without this
feature it seems that the abrupt termination of the postmaster process
during system shutdown leaves the PostgreSQL data in a state where
postmaster cannot start up without manual intervention (the
postmaster.pid file, in particular).  Note that postmaster/postgres must
also ignore SIGHUP signals for this to work -- a separate patch.

The bulk of the patch is the usual stuff to enable a new command line
option and manage the registry value.  The interesting part of the code
is merely the new set_service_controls_accepted() function that enables
the service to accept the shutdown control, and the change to
service_handler() that treats the SERVICE_CONTROL_SHUTDOWN notification
exactly like SERVICE_CONTROL_STOP.  More elaborate handling of the
shutdown case is possible, such as sending STOP_PENDING messages until
the managed process actually terminates, but in practice this simple
scheme works just fine (for PostgreSQL at least).

-- 
Fred Yankowski           fred AT OntoSys DOT com      tel: +1.630.879.1312
Principal Consultant     www.OntoSys.com       fax: +1.630.879.1370
OntoSys, Inc             38W242 Deerpath Rd, Batavia, IL 60510, USA
--------------4B8487E3562AF76A6AD717ED
Content-Type: text/plain; charset=us-ascii;
 name="cygrunsrv.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="cygrunsrv.diff"

Index: crit.cc
===================================================================
RCS file: /home/cvs/cvsroot/src/cygrunsrv/crit.cc,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crit.cc
--- crit.cc	2001/05/18 20:10:32	1.1.1.1
+++ crit.cc	2001/06/15 19:19:43
@@ -69,4 +69,16 @@ set_service_status (DWORD state, DWORD c
   LeaveCriticalSection (&ssc);
 }
 
-
+void
+set_service_controls_accepted (bool accept_shutdown)
+{
+  EnterCriticalSection (&ssc);
+  if (ssh)
+    {
+      ss.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+      if (accept_shutdown)
+	ss.dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
+      SetServiceStatus(ssh, &ss);
+    }
+  LeaveCriticalSection (&ssc);
+}
Index: crit.h
===================================================================
RCS file: /home/cvs/cvsroot/src/cygrunsrv/crit.h,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 crit.h
--- crit.h	2001/05/18 20:10:32	1.1.1.1
+++ crit.h	2001/06/15 19:19:43
@@ -29,5 +29,6 @@ extern void set_service_status (DWORD st
 				DWORD check_point = 0,
 		                DWORD wait_hint = 0,
 				DWORD exit_code = NO_ERROR);
+extern void set_service_controls_accepted(bool shutdown);
 
 #endif /* _CRIT_H */
Index: cygrunsrv.cc
===================================================================
RCS file: /home/cvs/cvsroot/src/cygrunsrv/cygrunsrv.cc,v
retrieving revision 1.7
diff -u -p -r1.7 cygrunsrv.cc
--- cygrunsrv.cc	2001/05/31 16:09:09	1.7
+++ cygrunsrv.cc	2001/06/15 19:19:44
@@ -63,16 +63,18 @@ struct option longopts[] = {
   { "stdin", required_argument, NULL, '0' },
   { "stdout", required_argument, NULL, '1' },
   { "stderr", required_argument, NULL, '2' },
+  { "shutdown", no_argument, NULL, 'o' },
   { "help", no_argument, NULL, 'h' },
   { "version", no_argument, NULL, 'v' },
   { 0, no_argument, NULL, 0 }
 };
 
-char *opts = "I:R:S:E:p:a:c:e:d:u:w:t:s:y:0:1:2:hv";
+char *opts = "I:R:S:E:p:a:c:e:d:ou:w:t:s:y:0:1:2:hv";
 
 char *appname;
 char *svcname;
 DWORD termsig;
+DWORD shutdown;
 
 enum action_t {
   Undefined,
@@ -124,7 +126,7 @@ int
 install_registry_keys (const char *name, const char *path,
 		       char *args, char *dir, env_t *env, DWORD termsig,
 		       const char *in_stdin, const char *in_stdout,
-		       const char *in_stderr)
+		       const char *in_stderr, DWORD shutdown)
 {
   HKEY srv_key = NULL;
   HKEY env_key = NULL;
@@ -181,6 +183,11 @@ install_registry_keys (const char *name,
 		       (const BYTE *) in_stderr,
 		       strlen (in_stderr) + 1) != ERROR_SUCCESS)
       err_out (RegSetValueEx);
+  if (shutdown)
+    if (RegSetValueEx (srv_key, PARAM_SHUTDOWN, 0, REG_DWORD,
+		       (const BYTE *) &shutdown,
+		       sizeof(DWORD)) != ERROR_SUCCESS)
+      err_out (RegSetValueEx);
   RegFlushKey (srv_key);
 
 out:
@@ -248,7 +255,8 @@ reeval_io_path (int fd, char *&io_path, 
 int
 get_reg_entries (const char *name, char *&path, char *&args, char *&dir,
 		 env_t *&env, DWORD *termsig_p,
-		 char *&stdin_path, char *&stdout_path, char *&stderr_path)
+		 char *&stdin_path, char *&stdout_path, char *&stderr_path,
+		 DWORD *shutdown_p)
 {
   HKEY srv_key = NULL;
   HKEY env_key = NULL;
@@ -283,6 +291,11 @@ get_reg_entries (const char *name, char 
 		       (BYTE *) termsig_p,
 		       (size = sizeof(*termsig_p), &size)) != ERROR_SUCCESS)
     *termsig_p = SIGTERM;  // the default
+  /* Get (optional) shutdown flag. */
+  if (RegQueryValueEx (srv_key, PARAM_SHUTDOWN, 0, &type,
+		       (BYTE *) shutdown_p,
+		       (size = sizeof(*shutdown_p), &size)) != ERROR_SUCCESS)
+    *shutdown_p = 0;  // the default
   /* Get (optional) stdin/stdout/stderr redirection files. */
   if ((ret = get_opt_string_entry (srv_key, PARAM_STDIN, stdin_path)))
     goto out;
@@ -820,6 +833,7 @@ service_handler (DWORD ctrl)
   switch (ctrl)
     {
     case SERVICE_CONTROL_STOP:
+    case SERVICE_CONTROL_SHUTDOWN:
       /* Since the service_handler doesn't run in the same thread as
          the service_main routine, it has to setup exception handling. */
       exception_list except_list;
@@ -895,13 +909,15 @@ service_main (DWORD argc, LPSTR *argv)
   char *stdout_path = NULL;
   char *stderr_path = NULL;
   if (err = get_reg_entries (svcname, path, args, dir, env, &termsig,
-			     stdin_path, stdout_path, stderr_path))
+			     stdin_path, stdout_path, stderr_path,
+			     &shutdown))
     {
       syslog_starterr ("get_reg_entries", err);
       set_service_status (SERVICE_STOPPED, 0, 0, err);
       return;
     }
   
+  set_service_controls_accepted ( shutdown );
   report_service_status ();
 
   /* Step 2: Further preparations:
@@ -1026,6 +1042,7 @@ main (int argc, char **argv)
   char *in_stdin = NULL;
   char *in_stdout = NULL;
   char *in_stderr = NULL;
+  int in_shutdown = 0;
 
   appname = argv[0];
 
@@ -1107,6 +1124,13 @@ main (int argc, char **argv)
 	  return error (OnlyOneDisp);
 	in_disp = optarg;
 	break;
+      case 'o':
+	if (action != Install)
+	  return error (ShutdownNotAllowed);
+	if (in_shutdown)
+	  return error (OnlyOneShutdown);
+	in_shutdown = 1;
+	break;
       case 's':
 	if (action != Install)
 	  return error (SigNotAllowed);
@@ -1199,7 +1223,8 @@ main (int argc, char **argv)
         return ret;
       if (ret = install_registry_keys (in_name, in_path, in_args, in_dir,
 				       in_env, in_termsig,
-				       in_stdin, in_stdout, in_stderr))
+				       in_stdin, in_stdout, in_stderr,
+				       in_shutdown))
         remove_service (in_name);
       return ret;
       break;
Index: cygrunsrv.h
===================================================================
RCS file: /home/cvs/cvsroot/src/cygrunsrv/cygrunsrv.h,v
retrieving revision 1.6
diff -u -p -r1.6 cygrunsrv.h
--- cygrunsrv.h	2001/05/31 16:09:09	1.6
+++ cygrunsrv.h	2001/06/15 19:19:44
@@ -31,6 +31,7 @@
 #define PARAM_STDERR	"StdErr"
 #define PARAM_ENVIRON	"Environment"
 #define PARAM_TERMSIG	"TermSig"
+#define PARAM_SHUTDOWN	"Shutdown"
 
 #define DEF_STDIN_PATH	"/dev/null"
 #define DEF_LOG_PATH	"/var/log/"
Index: utils.cc
===================================================================
RCS file: /home/cvs/cvsroot/src/cygrunsrv/utils.cc,v
retrieving revision 1.6
diff -u -p -r1.6 utils.cc
--- utils.cc	2001/05/31 16:09:09	1.6
+++ utils.cc	2001/06/15 19:19:44
@@ -57,6 +57,8 @@ char *reason_list[] = {
   "--dep is only allowed with --install",
   "--std{in,out,err} are only allowed with --install",
   "Each of --std{in,out,err} is allowed only once",
+  "--shutdown is only allowed with --install",
+  "Only one --shutdown is allowed",
   "Trailing commandline arguments not allowed",
   "You must specify one of the `-IRSE' options",
   "Error installing a service",
@@ -159,6 +161,7 @@ usage ()
   uprint ("                            Default is /var/log/<svc_name>.log.");
   uprint ("  -2, --stderr <file>       Optional output file used for stderr redirection.");
   uprint ("                            Default is /var/log/<svc_name>.log.");
+  uprint ("  -o, --shutdown            Stop service application during system shutdown.");
   uprint ("\nInformative output:");
   uprint ("  -h, --help                print this help, then exit.");
   uprint ("  -v, --version             print cygrunsrv program version number, then exit.");
Index: utils.h
===================================================================
RCS file: /home/cvs/cvsroot/src/cygrunsrv/utils.h,v
retrieving revision 1.5
diff -u -p -r1.5 utils.h
--- utils.h	2001/05/31 16:09:09	1.5
+++ utils.h	2001/06/15 19:19:44
@@ -48,6 +48,8 @@ enum reason_t {
   DepNotAllowed,
   IONotAllowed,
   OnlyOneIO,
+  ShutdownNotAllowed,
+  OnlyOneShutdown,
   TrailingArgs,
   StartAsSvcErr,
   InstallErr,

--------------4B8487E3562AF76A6AD717ED
Content-Type: text/plain; charset=us-ascii;
 name="cygrunsrv.changelog"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="cygrunsrv.changelog"

Index: ChangeLog
===================================================================
RCS file: /home/cvs/cvsroot/src/cygrunsrv/ChangeLog,v
retrieving revision 1.11
diff -u -p -r1.11 ChangeLog
--- ChangeLog	2001/05/31 16:09:09	1.11
+++ ChangeLog	2001/06/15 19:19:43
@@ -1,3 +1,24 @@
+2001-06-15  Fred Yankowski  <fred AT ontosys DOT com>
+
+	* utils.h (reason_t): Add codes for --shutdown errors.
+	* utils.cc (reason_list): Add error strings for --shutdown.
+	(usage): Add help text for --shutdown option.
+	* cygrunsrv.h (PARAM_SHUTDOWN): New registry name for shutdown
+	parameter.
+	* cygrunsrv.cc (longopts): Add '--shutdown' option.
+	(opts): Add '-o' option.
+	(shutdown): Define new global.
+	(install_registry_keys): Add 'shutdown' parameter, and writing
+	parameter to registry.
+	(get_reg_entries): Add 'shutdown_p' parameter and reading
+	parameter from registry.
+	(service_handler): Case for SERVICE_CONTROL_SHUTDOWN control.
+	(service_main): Set global 'shutdown' parameter, and call
+	set_service_controls_accepted.
+	(main): Add handling for '--shutdown' parameter.
+	* crit.h (set_service_controls_accepted): Declare new function.
+	* crit.cc (set_service_controls_accepted): New function.
+
 2001-05-31  Corinna Vinschen <corinna AT vinschen DOT de>
 
 	* cygrunsrv.cc (longopts): Add `--chdir' option.

--------------4B8487E3562AF76A6AD717ED--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019