[Zope-Checkins] CVS: Zope/lib/python/nt_svcutils -
service.py:1.4.2.1
Jeremy Hylton
jeremy at zope.com
Mon Jan 26 12:13:56 EST 2004
Update of /cvs-repository/Zope/lib/python/nt_svcutils
In directory cvs.zope.org:/tmp/cvs-serv20862/Zope/lib/python/nt_svcutils
Modified Files:
Tag: jeremy-windows-service-branch
service.py
Log Message:
Checkpoint of code to redirect stdout/stderr of spwaned
process to a file.
=== Zope/lib/python/nt_svcutils/service.py 1.4 => 1.4.2.1 ===
--- Zope/lib/python/nt_svcutils/service.py:1.4 Tue Jan 13 17:37:02 2004
+++ Zope/lib/python/nt_svcutils/service.py Mon Jan 26 12:13:55 2004
@@ -14,6 +14,7 @@
"""Windows Services installer/controller for Zope/ZEO/ZRS instance homes"""
+import msvcrt
import win32api
import win32con
import win32event
@@ -77,6 +78,7 @@
win32event.SetEvent(self.hWaitStop)
def createProcess(self, cmd):
+ self.start_time = time.time()
if self.capture_io:
return self.createProcessCaptureIO(cmd)
else:
@@ -126,56 +128,93 @@
# BACKOFF_CLEAR_TIME seconds, the backoff stats are reset.
# the initial number of seconds between process start attempts
- backoff_interval = BACKOFF_INITIAL_INTERVAL
+ self.backoff_interval = BACKOFF_INITIAL_INTERVAL
# the cumulative backoff seconds counter
- backoff_cumulative = 0
+ self.backoff_cumulative = 0
import servicemanager
self.logmsg(servicemanager.PYS_SERVICE_STARTED)
while 1:
- start_time = time.time()
info, handles = self.createProcess(self.start_cmd)
# XXX integrate handles into the wait and make a loop
# that reads data and writes it into a logfile
self.hZope = info[0] # the pid
- if backoff_interval > BACKOFF_INITIAL_INTERVAL:
+ # XXX why the test before the log message?
+ if self.backoff_interval > BACKOFF_INITIAL_INTERVAL:
self.info("created process")
+ if not (self.run(handles) and self.checkRestart()):
+ break
+ self.logmsg(servicemanager.PYS_SERVICE_STOPPED)
+
+ def run(self, handles):
+ """Monitor the daemon process.
+
+ Returns True if the service should continue running and
+ False if the service process should exit. On True return,
+ the process exited unexpectedly and the caller should restart
+ it.
+ """
+
+ keep_running = True
+ # ignore stdin
+ print handles
+ win32file.CloseHandle(handles[0])
+ fd = msvcrt.open_osfhandle(handles[1], 0)
+ stdout = os.fdopen(fd)
+ fd = msvcrt.open_osfhandle(handles[2], 0)
+ stderr = os.fdopen(fd)
+## stdout = os.fdopen(msvcrt.open_osfhandle(handles[1], 0))
+## stderr = os.fdopen(msvcrt.open_osfhandle(handles[2], 0))
+
+ while 1:
rc = win32event.WaitForMultipleObjects(
- (self.hWaitStop, self.hZope) + handles, 0, win32event.INFINITE)
+ (self.hWaitStop, self.hZope) + handles[1:], 0, win32event.INFINITE)
if rc == win32event.WAIT_OBJECT_0:
# user sent a stop service request
self.SvcStop()
+ keep_running = False
break
- else:
+ elif rc == win32event.WAIT_OBJECT_0 + 1:
# user did not send a service stop request, but
# the process died; this may be an error condition
status = win32process.GetExitCodeProcess(self.hZope)
- if status == 0:
- # the user shut the process down from the web
- # interface (or it otherwise exited cleanly)
- break
- else:
- # this was an abormal shutdown.
- if backoff_cumulative > BACKOFF_MAX:
- self.error("restarting too frequently; quit")
- self.SvcStop()
- break
- self.warning("sleep %s to avoid rapid restarts"
- % backoff_interval)
- if time.time() - start_time > BACKOFF_CLEAR_TIME:
- backoff_interval = BACKOFF_INITIAL_INTERVAL
- backoff_cumulative = 0
- # XXX Since this is async code, it would be better
- # done by sending and catching a timed event (a
- # service stop request will need to wait for us to
- # stop sleeping), but this works well enough for me.
- time.sleep(backoff_interval)
- backoff_cumulative += backoff_interval
- backoff_interval *= 2
-
- self.logmsg(servicemanager.PYS_SERVICE_STOPPED)
-
+ # exit status 0 means the user caused a clean shutdown,
+ # presumably via the web interface
+ keep_running = status != 0
+ break
+ else:
+ i = rc - (win32event.WAIT_OBJECT_0 + 2)
+ if i == 0:
+ data = stdout.read(8192)
+ self.info("stdout: %s" % data)
+ elif i == 1:
+ data = stderr.read(8192)
+ self.info("stderr: %s" % data)
+ stdout.close()
+ stderr.close()
+ return keep_running
+
+ def checkRestart(self):
+ # this was an abormal shutdown.
+ if self.backoff_cumulative > BACKOFF_MAX:
+ self.error("restarting too frequently; quit")
+ self.SvcStop()
+ return False
+ self.warning("sleep %s to avoid rapid restarts"
+ % self.backoff_interval)
+ if time.time() - self.start_time > BACKOFF_CLEAR_TIME:
+ self.backoff_interval = BACKOFF_INITIAL_INTERVAL
+ self.backoff_cumulative = 0
+ # XXX Since this is async code, it would be better
+ # done by sending and catching a timed event (a
+ # service stop request will need to wait for us to
+ # stop sleeping), but this works well enough for me.
+ time.sleep(self.backoff_interval)
+ self.backoff_cumulative += self.backoff_interval
+ self.backoff_interval *= 2
+ return True
+
def createProcessCaptureIO(self, cmd):
stdin = self.newPipe()
stdout = self.newPipe()
@@ -198,6 +237,7 @@
# circumstances of a service process.
info = win32process.CreateProcess(None, cmd, None, None, True, 0,
None, None, si)
+ print "createprocess", info
win32file.CloseHandle(stdin[0])
win32file.CloseHandle(stdout[1])
More information about the Zope-Checkins
mailing list