[Zope-Checkins] CVS: Packages/ZEO - component.xml:1.4.6.1 mkzeoinst.py:1.18.8.4 runzeo.py:1.15.6.5

Sidnei da Silva sidnei at awkly.org
Tue Apr 12 22:54:55 EDT 2005


Update of /cvs-repository/Packages/ZEO
In directory cvs.zope.org:/tmp/cvs-serv13625

Modified Files:
      Tag: Zope-2_7-branch
	component.xml mkzeoinst.py runzeo.py 
Log Message:

* Borrow Zope's 'Signal' mechanism for Windows, if available, to
  implement clean shutdown and log rotation handlers for Windows.
* Back to creating a .PID for ZEO, so external programs that wish to set
  the 'signal' can get the PID and therefore derive the signal name.
  Currently only necessary on Windows but created on all platforms which
  implement os.getpid(), as long as the 'pid-filename' option is set,
  or the 'INSTANCE_HOME' environment variable can be found.


=== Packages/ZEO/component.xml 1.4 => 1.4.6.1 ===
--- Packages/ZEO/component.xml:1.4	Fri May 30 15:20:57 2003
+++ Packages/ZEO/component.xml	Tue Apr 12 22:54:54 2005
@@ -93,6 +93,15 @@
       </description>
     </key>
 
+    <key name="pid-filename" datatype="existing-dirpath"
+         required="no">
+      <description>
+        The full path to the file in which to write the ZEO server's Process ID
+        at startup. If omitted, $INSTANCE/var/ZEO.pid is used.
+      </description>
+      <metadefault>$INSTANCE/var/ZEO.pid (or $clienthome/ZEO.pid)</metadefault>
+    </key>
+
   </sectiontype>
 
 </component>


=== Packages/ZEO/mkzeoinst.py 1.18.8.3 => 1.18.8.4 ===
--- Packages/ZEO/mkzeoinst.py:1.18.8.3	Wed Feb 18 17:10:14 2004
+++ Packages/ZEO/mkzeoinst.py	Tue Apr 12 22:54:54 2005
@@ -47,6 +47,7 @@
   address %(port)d
   read-only false
   invalidation-queue-size 100
+  # pid-filename $INSTANCE/var/ZEO.pid
   # monitor-address PORT
   # transaction-timeout SECONDS
 </zeo>


=== Packages/ZEO/runzeo.py 1.15.6.4 => 1.15.6.5 ===
--- Packages/ZEO/runzeo.py:1.15.6.4	Wed Jan 14 14:07:00 2004
+++ Packages/ZEO/runzeo.py	Tue Apr 12 22:54:54 2005
@@ -48,6 +48,11 @@
     obj = ZConfig.datatypes.SocketAddress(arg)
     return obj.family, obj.address
 
+def windows_shutdown_handler():
+    # Called by the signal mechanism on Windows to perform shutdown.
+    import asyncore
+    asyncore.close_all()
+
 class ZEOOptionsMixin:
 
     storages = None
@@ -95,6 +100,8 @@
                  None, 'auth-database=')
         self.add('auth_realm', 'zeo.authentication_realm',
                  None, 'auth-realm=')
+        self.add('pid_file', 'zeo.pid_filename',
+                 None, 'pid-file=')
 
 class ZEOOptions(ZDOptions, ZEOOptionsMixin):
 
@@ -117,6 +124,7 @@
         self.setup_default_logging()
         self.check_socket()
         self.clear_socket()
+        self.make_pidfile()
         try:
             self.open_storages()
             self.setup_signals()
@@ -125,6 +133,7 @@
         finally:
             self.close_storages()
             self.clear_socket()
+            self.remove_pidfile()
 
     def setup_default_logging(self):
         if self.options.config_logger is not None:
@@ -175,6 +184,8 @@
         method is called without additional arguments.
         """
         if os.name != "posix":
+            if os.name == "nt":
+                self.setup_win32_signals()
             return
         if hasattr(signal, 'SIGXFSZ'):
             signal.signal(signal.SIGXFSZ, signal.SIG_IGN) # Special case
@@ -186,6 +197,27 @@
                     method()
                 signal.signal(sig, wrapper)
 
+    def setup_win32_signals(self):
+        # Borrow the Zope Signals package win32 support, if available.
+        # Signals does a check/log for the availability of pywin32.
+        try:
+            import Signals.Signals
+        except ImportError:
+            debug("Signals package not found. "
+                  "Windows-specific signal handler "
+                  "will *not* be installed.")
+            return
+        SignalHandler = Signals.Signals.SignalHandler
+        if SignalHandler is not None: # may be None if no pywin32.
+            SignalHandler.registerHandler(signal.SIGTERM,
+                                          windows_shutdown_handler)
+            SignalHandler.registerHandler(signal.SIGINT,
+                                          windows_shutdown_handler)
+            # Can use the log rotate handler too.
+            from Signals.Signals import logfileRotateHandler
+            SIGUSR2 = 12 # not in signal module on Windows.
+            SignalHandler.registerHandler(SIGUSR2, logfileRotateHandler)
+
     def create_server(self):
         from ZEO.StorageServer import StorageServer
         self.server = StorageServer(
@@ -232,6 +264,53 @@
             except: # Keep going
                 exception("failed to close storage %r" % name)
 
+    def _get_pidfile(self):
+        pidfile = self.options.pid_file
+        # 'pidfile' is marked as not required.
+        if not pidfile:
+            # Try to find a reasonable location if the pidfile is not
+            # set. If we are running in a Zope environment, we can
+            # safely assume INSTANCE_HOME.
+            instance_home = os.environ.get("INSTANCE_HOME")
+            if not instance_home:
+                # If all our attempts failed, just log a message and
+                # proceed.
+                debug("'pidfile' option not set, and 'INSTANCE_HOME' "
+                      "environment variable could not be found. "
+                      "Cannot guess pidfile location.")
+                return
+            pidfile = os.path.join(instance_home, "var", "ZEO.pid")
+        return pidfile
+
+    def make_pidfile(self):
+        if not self.options.read_only:
+            pidfile = self._get_pidfile()
+            if pidfile is None:
+                return
+            try:
+                if os.path.exists(pidfile):
+                    os.unlink(pidfile)
+                pid = os.getpid()
+                f = open(pidfile, 'w')
+                f.write(`pid`)
+                f.close()
+                info("created PID file '%s'" % pidfile)
+            except IOError:
+                error("PID file '%s' cannot be opened" % pidfile)
+            except AttributeError:
+                pass  # getpid not supported. Unix/Win only
+
+    def remove_pidfile(self):
+        if not self.options.read_only:
+            pidfile = self._get_pidfile()
+            if pidfile is None:
+                return
+            try:
+                if os.path.exists(pidfile):
+                    os.unlink(pidfile)
+                    info("removed PID file '%s'" % pidfile)
+            except IOError:
+                error("PID file '%s' could not be removed")
 
 # Signal names
 



More information about the Zope-Checkins mailing list