[Zodb-checkins] CVS: ZODB3/zdaemon - Daemon.py:1.11.8.1 ZDaemonLogging.py:1.4.8.1 SignalPasser.py:NONE
Guido van Rossum
guido@python.org
Thu, 17 Oct 2002 18:10:48 -0400
Update of /cvs-repository/ZODB3/zdaemon
In directory cvs.zope.org:/tmp/cvs-serv522
Modified Files:
Tag: ZODB3-3_1-branch
Daemon.py ZDaemonLogging.py
Removed Files:
Tag: ZODB3-3_1-branch
SignalPasser.py
Log Message:
Merge trunk; fixes and refactorings by ChrisM, presentation by Guido.
=== ZODB3/zdaemon/Daemon.py 1.11 => 1.11.8.1 ===
--- ZODB3/zdaemon/Daemon.py:1.11 Wed Aug 14 18:12:52 2002
+++ ZODB3/zdaemon/Daemon.py Thu Oct 17 18:10:48 2002
@@ -15,13 +15,31 @@
import os, sys, time, signal
from ZDaemonLogging import pstamp
import zLOG
-from SignalPasser import SignalPasser
+
+# If zdaemon finds that it is continuously respawning more than 10
+# times in 2 minutes, it will assume that there is an error, log a
+# PANIC level message, and exit.
+RESPAWN_TIME = 120 # 2 minutes
+RESPAWN_LIMIT = 10 # 10 times
pyth = sys.executable
class DieNow(Exception):
pass
+class SignalPasser:
+ """ A class used for passing signal that the daemon receives along to
+ its child """
+ def __init__(self, pid):
+ self.pid = pid
+
+ def __call__(self, signum, frame):
+ # send the signal to our child
+ os.kill(self.pid, signum)
+ # we want to die ourselves if we're signaled with SIGTERM or SIGINT
+ if signum in [signal.SIGTERM, signal.SIGINT]:
+ raise DieNow
+
def run(argv, pidfile=''):
if os.environ.has_key('ZDAEMON_MANAGED'):
# We're being run by the child.
@@ -32,7 +50,17 @@
if not os.environ.has_key('Z_DEBUG_MODE'):
detach() # detach from the controlling terminal
+ starttimes = [] # for RESPAWN_LIMIT
while 1:
+ # Give up if respawning too often
+ starttimes.append(time.time())
+ if len(starttimes) > RESPAWN_LIMIT:
+ del starttimes[0]
+ if starttimes[-1] - starttimes[0] < RESPAWN_TIME:
+ pstamp('Respawning more than %d times in %d seconds. Quit.' %
+ (RESPAWN_LIMIT, RESPAWN_TIME), zLOG.PANIC)
+ sys.exit(1)
+ del starttimes[0]
try:
pid = os.fork()
if pid:
@@ -42,8 +70,8 @@
interesting = [1, 2, 3, 10, 12, 15]
# ie. HUP, INT, QUIT, USR1, USR2, TERM
for sig in interesting:
- signal.signal(sig, SignalPasser(sig))
- pstamp('Houston, we have forked: pid %s' % pid, zLOG.INFO)
+ signal.signal(sig, SignalPasser(pid))
+ pstamp('Started subprocess: pid %s' % pid, zLOG.INFO)
write_pidfile(pidfile)
p,s = wait(pid) # waitpid will block until child exit
if s:
@@ -79,7 +107,7 @@
def write_pidfile(pidfile):
if pidfile:
pf = open(pidfile, 'w+')
- pf.write(("%s" % os.getpid()))
+ pf.write(("%s\n" % os.getpid()))
pf.close()
def wait(pid):
@@ -101,28 +129,19 @@
elif os.WIFSIGNALED(s):
signum = os.WTERMSIG(s)
signame = get_signal_name(signum)
- msg = "terminated by signal %s(%s)" % (signame,
- signum)
- # We'd like to report whether a core file
- # was produced, but there isn't a standard
- # way to check. It seems that some
- # (many?) Unixes use bit 0x80 in the wait
- # status, but how to tell? A simple
- # alternative is to assume that no core
- # file was produced if the wait status is
- # exactly equal to the signal. Otherwise,
- # there might be a core file and it's
- # useful to print the wait status.
- if signum != s:
- msg += ", wait status: %s" % signum
+ msg = "terminated by signal %s(%s)" % (signame, signum)
+ if hasattr(os, 'WCOREDUMP'):
+ iscore = os.WCOREDUMP(s)
+ else:
+ iscore = s & 0x80
+ if iscore:
+ msg += " (core dumped)"
else:
# XXX what should we do here?
signum = os.WSTOPSIG(s)
signame = get_signal_name(signum)
- msg = "stopped by signal %s(%s)" % (signame,
- signum)
- pstamp('Aiieee! Process %s %s' % (p, msg),
- zLOG.ERROR)
+ msg = "stopped by signal %s(%s)" % (signame, signum)
+ pstamp('Process %s %s' % (p, msg), zLOG.ERROR)
_signals = None
=== ZODB3/zdaemon/ZDaemonLogging.py 1.4 => 1.4.8.1 ===
--- ZODB3/zdaemon/ZDaemonLogging.py:1.4 Wed Aug 14 18:12:52 2002
+++ ZODB3/zdaemon/ZDaemonLogging.py Thu Oct 17 18:10:48 2002
@@ -17,5 +17,4 @@
from zLOG import LOG
def pstamp(message, sev):
- LOG("zdaemon", sev,
- ("zdaemon: %s: %s" % (ctime(time()), message)))
+ LOG("zdaemon", sev, message)
=== Removed File ZODB3/zdaemon/SignalPasser.py ===