Browse Source

Making Ctrl+C the default behaviour

also making the timeout customizable, plus documentation
Kohsuke Kawaguchi 12 years ago
parent
commit
ae1bc43cff
4 changed files with 32 additions and 33 deletions
  1. 13 21
      Main.cs
  2. 8 1
      README.markdown
  3. 8 8
      ServiceDescriptor.cs
  4. 3 3
      SigIntHelper.cs

+ 13 - 21
Main.cs

@@ -337,33 +337,25 @@ namespace winsw
                 StopProcessAndChildren(Convert.ToInt32(mo["ProcessID"]));
             }
 
-            try
+            var proc = Process.GetProcessById(pid);
+            WriteEvent("Send SIGINT " + process.Id);
+            bool successful = SigIntHelper.SendSIGINTToProcess(proc,descriptor.StopTimeout);
+            if (successful)
+            {
+                WriteEvent("SIGINT to" + process.Id + " successful");
+            }
+            else
             {
-                var proc = Process.GetProcessById(pid);
-                if (descriptor.SendSIGINT)
+                try
                 {
-                    WriteEvent("Send SIGINT " + process.Id);
-                    bool successful = SigIntHelper.SendSIGINTToProcess(proc);
-                    if (successful)
-                    {
-                        WriteEvent("SIGINT to" + process.Id + " successful");
-                    }
-                    else
-                    {
-                        WriteEvent("SIGINT to " + process.Id + " failed - Killing as fallback");
-                        proc.Kill();
-                    }
+                    WriteEvent("SIGINT to " + process.Id + " failed - Killing as fallback");
+                    proc.Kill();
                 }
-                else
+                catch (ArgumentException)
                 {
-                    WriteEvent("ProcessKill " + process.Id);
-                    proc.Kill();
+                    // Process already exited.
                 }
             }
-            catch (ArgumentException)
-            {
-                // Process already exited.
-            }
         }
 
         private void WaitForProcessToExit(Process process)

+ 8 - 1
README.markdown

@@ -185,6 +185,13 @@ When you use the `<stopargument>`, you must use `<startargument>` instead of `<a
     <stopexecutable>catalina.sh</stopexecutable>
     <stopargument>stop</stopargument>
 
+### stoptimeout
+When the service is requested to stop, winsw first attempts to <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms683155(v=vs.85).aspx">send Ctrl+C signal to the process</a>, then wait for up to 15 seconds for the process to exit by itself gracefully. A process failing to do that (or if the process does not have a console), then winsw resorts to calling <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms686714(v=vs.85).aspx">TerminateProcess</a> API to kill the service instantly.
+
+This optional element allows you to change this "15 seconds" value, so that you can control how long winsw gives the service to shut itself down. See `<onfailure>` below for how to specify time duration:
+
+    <stoptimeout>10sec</stoptimeout>
+
 ### env
 This optional element can be specified multiple times if necessary to specify environment variables to be set for the child process. The syntax is:
 
@@ -253,4 +260,4 @@ It is possible to specify the useraccount (and password) that the service will r
 ### Working directory
 Some services need to run with a working directory specified. To do this, specify a `<workingdirectory>` element like this:
 
-    <workingdirectory>C:\application</workingdirectory>
+    <workingdirectory>C:\application</workingdirectory>

+ 8 - 8
ServiceDescriptor.cs

@@ -562,14 +562,14 @@ namespace winsw
 		}
 
          /// <summary>
-         /// True if the service can interact with the desktop.
+         /// Time to wait for the service to gracefully shutdown before we forcibly kill it
          /// </summary>
-         public bool SendSIGINT
-         {
-             get
-             {
-                 return dom.SelectSingleNode("//sendsigint") != null;
-             }
-         }
+        public TimeSpan StopTimeout
+        {
+            get
+            {
+                return SingleTimeSpanElement(dom, "stoptimeout", TimeSpan.FromSeconds(15));
+            }
+        }
     }
 }

+ 3 - 3
SigIntHelper.cs

@@ -41,7 +41,7 @@ namespace winsw
         /// </summary>
         /// <param name="process">The process to attach to and send the SIGINT</param>
         /// <returns>True if the process shut down successfully to the SIGINT, false if it did not.</returns>
-        public static bool SendSIGINTToProcess(Process process)
+        public static bool SendSIGINTToProcess(Process process, TimeSpan shutdownTimeout)
         {
             if (AttachConsole((uint)process.Id))
             {
@@ -49,7 +49,7 @@ namespace winsw
                 SetConsoleCtrlHandler(null, true);
                 GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0);
 
-                process.WaitForExit(15000);
+                process.WaitForExit(shutdownTimeout.TotalMilliseconds);
 
                 return process.HasExited;
             }
@@ -59,4 +59,4 @@ namespace winsw
             }
         }
     }
-}
+}