Commits

Eric Larson committed 7e82a19 Draft

Handle restarts by using the pid when the Popen object is gone after an exec.

Comments (0)

Files changed (1)

 import glob
 import subprocess
 import shlex
+import signal
 
 from cherrypy.process.plugins import Autoreloader
 from cherrypy.process.plugins import SimplePlugin
         self.cmd = None
         self.args = []
         self.kw = {}
+        self.pid = None
 
     def start(self):
-        if self.cmd:
+        """
+        Start our process and store our Popen object and pid.
+        """
+        if self.cmd and not self.pid:
+            # We can use a list or a string for the command.
             if isinstance(self.cmd, basestring):
                 self.cmd = shlex.split(self.cmd)
+
+            # Start our process
             self.proc = subprocess.Popen(self.cmd,
                                          *self.args,
                                          **self.kw)
+            # Store the pid separately. When cherrypy restarts it does
+            # an exec which kills our Popen instance. We can use the
+            # pid to stop the process safely.
+            self.pid = self.proc.pid
+
+    def kill(self):
+        """
+        Stop the process via the Popen object or pid.
+        """
+        if self.proc and self.proc.poll():
+            # We trust the process will end happily with a
+            # SIGTERM. Might need a hook to help things along if it
+            # doesn't stop nicely.
+            self.proc.terminate()
+            self.proc.wait()
+        elif self.pid:
+            # We have been restarted which means our proc object is
+            # gone. We can still use our pid and os.kill directly.
+            os.kill(self.pid, signal.SIGTERM)
 
     def stop(self):
-        if self.proc and self.proc.poll():
-            self.proc.terminate()
-            self.proc.wait()
+        self.kill()
 
 
 if __name__ == '__main__':