[Zope-Checkins] CVS: Zope/lib/python/Controller - Main.py:1.1.2.7 ZctlLib.py:1.1.2.3 directives.csv:1.1.2.7

Chris McDonough chrism@zope.com
Sun, 6 Oct 2002 02:06:00 -0400


Update of /cvs-repository/Zope/lib/python/Controller
In directory cvs.zope.org:/tmp/cvs-serv20017/lib/python/Controller

Modified Files:
      Tag: chrism-install-branch
	Main.py ZctlLib.py directives.csv 
Log Message:
Win32-related fixes for zctl and Zope.

Use a dedicated lockfile instead of locking the pid file.  On Win32, locks
are not advisory, so you can't read the pidfile from a process which
does not hold the lock.

Made zctl debug and zctl run work under Windows.




=== Zope/lib/python/Controller/Main.py 1.1.2.6 => 1.1.2.7 ===
--- Zope/lib/python/Controller/Main.py:1.1.2.6	Sun Oct  6 00:32:38 2002
+++ Zope/lib/python/Controller/Main.py	Sun Oct  6 02:05:58 2002
@@ -54,6 +54,10 @@
                           config.get('use_daemon_process'))
     PID_FILE           = (config.get('pid_filename') or
                           os.path.join(INSTANCE_HOME, 'var', 'Z2.pid'))
+    # we need a separate lock file because on win32, locks are not advisory
+    # otherwise we would just use the pid file
+    LOCK_FILE          = (config.get('lock_filename') or
+                          os.path.join(INSTANCE_HOME, 'var', 'Z2.lock'))
 
     # z2.py writes all envvars on command line into HTTP_ENV.
     # we don't bother because I can't think of a configuration in which
@@ -459,21 +463,24 @@
                 'your Zope data, it is recommended you use 077' % current_umask
                 ))
 
-    # lock_file is used for the benefit of zctl, so it can tell whether
-    # Zope is already running before attempting to fire it off again.
-    # We aren't concerned about locking the file to protect against
-    # other Zope instances running from our CLIENT_HOME, we just
-    # try to lock the file to signal that zctl should not try to
-    # start Zope if *it* can't lock the file; we don't panic
-    # if we can't lock it.
     if not READ_ONLY:
-        if os.path.exists(PID_FILE):
-            os.unlink(PID_FILE)
-        pf = open(PID_FILE, 'w')
+        # lock_file is used for the benefit of zctl, so it can tell whether
+        # Zope is already running before attempting to fire it off again.
+        # We aren't concerned about locking the file to protect against
+        # other Zope instances running from our CLIENT_HOME, we just
+        # try to lock the file to signal that zctl should not try to
+        # start Zope if *it* can't lock the file; we don't panic
+        # if we can't lock it.
         try:
-            lock_file(pf)
-        except:
+            if os.path.exists(LOCK_FILE):
+                os.unlink(LOCK_FILE)
+            lf = open(LOCK_FILE, 'w')
+            lock_file(lf)
+        except IOError:
             pass
+            
+        # write pid file
+        pf = open(PID_FILE, 'w')
         pid=str(os.getpid())
         try: pid=str(os.getppid())+' '+pid
         except: pass
@@ -493,6 +500,11 @@
         if not READ_ONLY:
             pf.close()
             os.unlink(PID_FILE)
+            try:
+                lf.close()
+                os.unlink(LOCK_FILE)
+            except:
+                pass
 
 def _warn_nobody():
     import zLOG


=== Zope/lib/python/Controller/ZctlLib.py 1.1.2.2 => 1.1.2.3 ===
--- Zope/lib/python/Controller/ZctlLib.py:1.1.2.2	Sun Oct  6 00:32:38 2002
+++ Zope/lib/python/Controller/ZctlLib.py	Sun Oct  6 02:05:58 2002
@@ -113,7 +113,7 @@
             if lock_status:
                 self._report('Error:  cannot start Zope.  Another Zope '
                              'instance has locked the "%s" file.  Use "stop" '
-                             'to stop it.' %  self._getPidfileName())
+                             'to stop it.' %  self._getLockfileName())
                 self._report()
                 return
 
@@ -334,15 +334,19 @@
         swhome = self._getSoftwareHome()
         zopehome = self._getZopeHome()
         cmd = (
-            'import os, sys; os.environ["EVENT_LOG_SEVERITY"]="300"; '
-            'sys.path.insert(0, "%s"); sys.path.insert(0, "%s"); '
-            'import Controller.Directives; '
-            'Controller.Directives.DirectiveRegistry.reconfigure("%s");'
-            'import Zope; app=Zope.app(); execfile( "%s" )'
+            "import os, sys; os.environ['EVENT_LOG_SEVERITY']='300'; "
+            "sys.path.insert(0, '%s'); sys.path.insert(0, '%s'); "
+            "import Controller.Directives; "
+            "Controller.Directives.DirectiveRegistry.reconfigure('%s');"
+            "import Zope; app=Zope.app(); execfile( '%s' )"
                   % ( zopehome, swhome, CONFIG_LOCATION, arg )
                   )
+        cmd = cmdquote(cmd)
         self._report( 'Running script: %s' % arg )
-        status = self._spawnPython('-c', cmd)
+        try:
+            status = self._spawnPython('-c', cmd)
+        except KeyboardInterrupt:
+            pass
 
     def debug( self, arg ):
         """
@@ -353,17 +357,21 @@
         swhome = self._getSoftwareHome()
         zopehome = self._getZopeHome()
         cmd = (
-            'import os, sys; os.environ["EVENT_LOG_SEVERITY"]="300"; '
-            'sys.path.insert(0, "%s"); sys.path.insert(0, "%s"); '
-            'import Controller.Directives;'
-            'Controller.Directives.DirectiveRegistry.reconfigure("%s");'
-            'import Zope; app=Zope.app()'
+            "import os, sys; os.environ['EVENT_LOG_SEVERITY']='300'; "
+            "sys.path.insert(0, '%s'); sys.path.insert(0, '%s'); "
+            "import Controller.Directives; "
+            "Controller.Directives.DirectiveRegistry.reconfigure('%s');"
+            "import Zope; app=Zope.app()"
                   % ( zopehome, swhome, CONFIG_LOCATION)
                   )
+        cmd = cmdquote(cmd)
         msg = ('Starting debugger.  The name "app" will be bound to the Zope '
                '"root object" when you enter interactive mode.')
         self._report( msg )
-        status = self._spawnPython('-i', '-c', cmd)
+        try:
+            status = self._spawnPython('-i', '-c', cmd)
+        except KeyboardInterrupt:
+            pass
 
     #
     #   Helper functions
@@ -390,6 +398,9 @@
     def _getPidfileName(self):
         return self._config.get('pid_filename')
 
+    def _getLockfileName(self):
+        return self._config.get('lock_filename')
+
     def _getDirective(self, name):
         return self._config.get(name)
 
@@ -408,12 +419,6 @@
             l.append('%s=%s' % (k,v))
         return l
 
-##     def _doSystem( self, message, cmdline ):
-##         self._report( message )
-##         self._report( '   ' + cmdline )
-##         status = os.system( cmdline )
-##         return status
-
     def _spawnPython(self, *args, **kw):
         if not kw.has_key('wait'):
             startup = os.P_WAIT
@@ -501,7 +506,7 @@
         self._report( printable )
  
     def lockFile(self):
-        filename = os.path.join(self._getPidfileName())
+        filename = os.path.join(self._getLockfileName())
         if not os.path.exists(filename):
             return 0
         file = open(filename, 'r+')
@@ -711,22 +716,42 @@
         if pids:
             return [ int(x.strip()) for x in pids ]
 
-def kill(pid, sig):
-    if sys.platform == 'win32':
-        # we ignore the signal on win32
+def win32kill(pid, sig):
+    # we ignore the signal on win32
+    try:
         import win32api
+        import pywintypes
+    except:
+        print ("Could not open win32api module, have you installed the "
+               "'win32all' package?")
+        return 1
+    try:
         handle = win32api.OpenProcess(1, 0, pid)
-        try:
-            return (0 != win32api.TerminateProcess(handle, 0))
-        except:
-            return 1
+    except pywintypes.error, why:
+        # process named by pid not running
+        return 1
+    try:
+        status = win32api.TerminateProcess(handle, 0)
+    except:
+        return 1
+    if status is None:
+        return 0
+    return 1
+
+def kill(pid, sig):
+    try:
+        os.kill(pid, sig)
+    except OSError, why:
+        return 1
     else:
-        try:
-            os.kill(pid, sig)
-        except OSError, why:
-            return 1
-        else:
-            return 0
+        return 0
 
-    
-    
+def cmdquote(cmd):
+    if sys.platform == 'win32':
+        # ugh.  win32 requires the command to be quoted.  unix requires
+        # that the command *not* be quoted.
+        cmd = '"%s"' % cmd
+    return cmd
+
+if sys.platform == 'win32':
+    kill = win32kill


=== Zope/lib/python/Controller/directives.csv 1.1.2.6 => 1.1.2.7 ===
--- Zope/lib/python/Controller/directives.csv:1.1.2.6	Mon Sep 16 01:49:42 2002
+++ Zope/lib/python/Controller/directives.csv	Sun Oct  6 02:05:58 2002
@@ -12,6 +12,7 @@
 admin	55	use_daemon_process	If this directive is set to 'on', Zope will be managed by a 'daemon' process which will restart the Zope process if it dies unexpectedly.	cmd	onoff		on	1	on
 admin	60	zserver_read_only_mode	If this directive is set to 'on', it will cause Zope to inhibit the creation of log files and pid files.  Access and event log files will be presented on standard output.  Setting this directive 'on' causes pcgi, fastcgi, and daemon-related directives to have no effect.	cmd	onoff		off	None	on
 admin	65	pid_filename	The path to the file in which the Zope process id(s) will be written.  This defaults to client_home/Z2.pid.	cmd	path		CLIENT_HOME/Z2.pid	pjoin(reg_get('client_home'), 'Z2.pid')	/home/chrism/projects/sessions/var/Z2.pid
+admin	66	lock_filename	The path to the file which the Zope process uses as a lock file.  This defaults to client_home/Z2.lock.	cmd	path		CLIENT_HOME/Z2.lock	pjoin(reg_get('client_home'), 'Z2.lock')	/home/chrism/projects/sessions/var/Z2.lock
 log	70	acccess_syslog_facility	Same as 'event_syslog_facility', only for the "access" log data (z2.log data).	env	string	ZSYSLOG_ACCESS_FACILITY	unset	None	local7
 log	75	access_log_filename	The file path of the Zope 'access' log (z2.log) which is written in the combined logfile format.  The access log will be printed to standard output if the 'zserver_read_only' directive is set to 'on', regardless of this setting.	cmd	string		CLIENT_HOME/z2.log	pjoin(reg_get('client_home'), 'Z2.log')	/home/chrism/projects/sessions/z2.log
 log	80	access_syslog_path	Same as event_syslog_path, only for the "access" log data (z2.log data).	env	path	ZSYSLOG_ACCESS	unset	None	/dev/log