Skip to content
This repository has been archived by the owner on Feb 13, 2020. It is now read-only.

Commit

Permalink
Refactored, but untested.
Browse files Browse the repository at this point in the history
Refactor the main SvcDoRun() method to make it a little easier to
read.  Move the details of log messages to helper methods.  Trim
comments that explain obvious code.

Make log messages read the same as zdaemon log messages.
  • Loading branch information
Jeremy Hylton committed Jan 13, 2004
1 parent f90745a commit 4a12cfb
Showing 1 changed file with 40 additions and 51 deletions.
91 changes: 40 additions & 51 deletions service.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
#
##############################################################################

""" Windows NT/2K service installer/controller for Zope/ZEO/ZRS instance
homes """
"""Windows Services installer/controller for Zope/ZEO/ZRS instance homes"""

import win32serviceutil
import win32service
Expand Down Expand Up @@ -74,10 +73,35 @@ def createProcess(self, cmd):
None, cmd, None, None, 0, 0, None, None,
win32process.STARTUPINFO())

def logmsg(self, event):
# log a service event using servicemanager.LogMsg
from servicemanager import LogMsg
LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, event,
(self._svc_name_, " (%s)" % self._svc_display_name_))

def info(self, s):
from servicemanager import LogInfoMsg
LogInfoMsg("%s (%s): %s" %
(self._svc_name_, self._svc_display_name_, s))

def warning(self, s):
from servicemanager import LogWarningMsg
LogWarningMsg("%s (%s): %s" %
(self._svc_name_, self._svc_display_name_, s))

def error(self, s):
from servicemanager import LogErrorMsg
LogErrorMsg("%s (%s): %s" %
(self._svc_name_, self._svc_display_name_, s))

def SvcDoRun(self):
# indicate to Zope that the process is daemon managed (restartable)
os.environ['ZMANAGED'] = '1'

# XXX the restart behavior is different here than it is for
# zdaemon.zdrun. we should probably do the same thing in both
# places.

# daemon behavior: we want to to restart the process if it
# dies, but if it dies too many times, we need to give up.

Expand All @@ -96,24 +120,14 @@ def SvcDoRun(self):
backoff_cumulative = 0

import servicemanager

# log a service started message
servicemanager.LogMsg(
servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ' (%s)' % self._svc_display_name_))
self.logmsg(servicemanager.PYS_SERVICE_STARTED)

while 1:
start_time = time.time()
info = self.createProcess(self.start_cmd)
self.hZope = info[0] # the pid
if backoff_interval > BACKOFF_INITIAL_INTERVAL:
# if we're in a backoff state, log a message about
# starting a new process
servicemanager.LogInfoMsg(
'%s (%s): recovering from died process, new process '
'started' % (self._svc_name_, self._svc_display_name_)
)
self.info("created process")
rc = win32event.WaitForMultipleObjects(
(self.hWaitStop, self.hZope), 0, win32event.INFINITE)
if rc == win32event.WAIT_OBJECT_0:
Expand All @@ -129,51 +143,26 @@ def SvcDoRun(self):
# interface (or it otherwise exited cleanly)
break
else:
# this was an abormal shutdown. if we can, we want to
# restart the process but if it seems hopeless,
# don't restart an infinite number of times.
# this was an abormal shutdown.
if backoff_cumulative > BACKOFF_MAX:
# it's hopeless
servicemanager.LogErrorMsg(
'%s (%s): process could not be restarted due to max '
'restart attempts exceeded' % (
self._svc_display_name_, self._svc_name_
))
self.error("restarting too frequently; quit")
self.SvcStop()
break
servicemanager.LogWarningMsg(
'%s (%s): process died unexpectedly. Will attempt '
'restart after %s seconds.' % (
self._svc_name_, self._svc_display_name_,
backoff_interval
)
)
# if BACKOFF_CLEAR_TIME seconds have elapsed since we last
# started the process, reset the backoff interval
# and the cumulative backoff time to their original
# states
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
# we sleep for the backoff interval. 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.
# 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)
# update backoff_cumulative with the time we spent
# backing off.
backoff_cumulative = backoff_cumulative + backoff_interval
# bump the backoff interval up by 2* the last interval
backoff_interval = backoff_interval * 2
backoff_cumulative += backoff_interval
backoff_interval *= 2

# loop and try to restart the process

# log a service stopped message
servicemanager.LogMsg(
servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STOPPED,
(self._svc_name_, ' (%s) ' % self._svc_display_name_))
self.logmsg(servicemanager.PYS_SERVICE_STOPPED)

if __name__=='__main__':
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(Service)

0 comments on commit 4a12cfb

Please sign in to comment.