remove dependencies on daemon and lockfile

This commit is contained in:
2016-05-18 10:33:37 -04:00
parent c3eb0f03fc
commit e4b3478dff
+80 -111
View File
@@ -17,48 +17,13 @@ import zlib
import subprocess
import syslog
try:
import lockfile
import daemon
import daemon.pidfile
except:
print """
require on Linux
python-filelock
python-daemon vs 1.61 or >
run sudo easy_install-2.7 lockfile python-daemon
on *bsd
py27-lockfile
py27-daemon
run sudo pkg install -y py27-lockfile py27-daemon
"""
sys.exit(1)
# N.B. daemon tries to close resource.RLIMIT_NOFILE file descriptors
# which on FreeBSD in close to a million
# hack: replace the function in daemon with ths one:
def log(msg):
if fdaemon:
syslog.syslog(syslog.LOG_ERR, msg)
else:
print msg
def get_maximum_file_descriptors():
return 2048
daemon.get_maximum_file_descriptors = get_maximum_file_descriptors
import syslog
PORT = 50003
INTERVAL = 10
PIDFILE = '/tmp/hbc.pid'
VER = 3
VER = 4
MAXRECV = 32767
running = True
@@ -66,8 +31,8 @@ dorestart = False
warned1 = False
class NullDevice:
def write(self, s):
pass
def write(self, s):
pass
class Conn:
@@ -84,7 +49,7 @@ class Conn:
self.rtts = [0]
self.sock=socket.socket(af, socket.SOCK_DGRAM)
self.sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, \
self.sock.getsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR) | 1)
self.sock.getsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR) | 1)
def sendto(self, msg, ID = 'HTB'): # default ID is HearTBeat
global warned1
@@ -175,8 +140,9 @@ def syslogtrace(note):
logm = '%s hbc died: \n%s' % (note, traceback.format_exc())
log(logm)
for l in logm.split('\n'):
log(' tb: %s' % l)
syslog.syslog(syslog.LOG_ERR, ' tb: %s' % l)
if verbose:
print logm
conId = 1
@@ -185,7 +151,7 @@ def createConnections(hosts):
for host in hosts:
if verbose: log("createConnections for %s" % host)
try:
rs=socket.getaddrinfo(host, hb_port, 0, 0, socket.SOL_UDP)
rs=socket.getaddrinfo(host, hb_port, 0, 0, socket.SOL_UDP)
except socket.gaierror:
logm = '%s hbc died: \n%s' % ('createConnections', traceback.format_exc())
if verbose: log(logm)
@@ -197,7 +163,7 @@ def createConnections(hosts):
elif r[0] == 2:
af=socket.AF_INET
else:
log("dont know this net type: %s" % r[0][0])
print "dont know this net type: %s" % r[0][0]
sys.exit(1)
addr = r[4][0]
@@ -226,7 +192,7 @@ def doupdate(conn, msgDict):
code = msgDict['code'].decode('base64')
csum = msgDict['csum']
except:
fail = "csum/code missing"
fail = "csum/code missing"
if not fail:
fail = doupdateone(code, csum)
@@ -244,10 +210,10 @@ def doupdateone(code, csum):
m.update(code)
icsum = m.hexdigest()
if icsum != csum:
return "checksum error"
return "checksum error"
fn = sys.argv[0]
ofn = "%.sav" % fn
ofn = "%.sav" % fn
try:
shutil.copy2(fn, ofn)
except Exception as e:
@@ -264,7 +230,9 @@ def doupdateone(code, csum):
def restart():
log('restart %s' % (sys.argv[0]))
if verbose:
print "restart: execv %s %s" % (sys.argv[0], [sys.argv[0]]+cmdargs)
syslog.syslog(syslog.LOG_ERR, 'restart %s' % (sys.argv[0]))
e = "fallthrough"
try:
os.execv(sys.argv[0], [sys.argv[0]]+cmdargs)
@@ -310,14 +278,14 @@ def process():
if verbose: print "sock.recvfrom: %s (%s) %s" % (addr, len(data), data[:4])
msgDict = stodict(data)
if verbose: print "sock.recvfrom: %s (%s) %s" % (addr, len(data), str(msgDict)[:80])
if msgDict['ID'] == "ACK":
if msgDict['ID'] == "ACK":
conns[conn].ack(msgDict)
elif msgDict['ID'] == "UPD":
elif msgDict['ID'] == "UPD":
if doupdate(conn, msgDict) == None:
if verbose: print "process: restart after update"
dorestart = True
break
elif msgDict['ID'] == "CMD":
elif msgDict['ID'] == "CMD":
doexec(conn, msgDict['cmd'])
else:
doexec(conn, data) # deprecated until no more VER - hbc
@@ -341,7 +309,7 @@ def cleanup():
global running
if verbose: log('cleanup')
running = False
for conn in conns:
for conn in conns:
msg={'shutdown': 1, 'acks': conns[conn].ackcount}
conns[conn].sendto(msg)
conns[conn].close()
@@ -350,15 +318,59 @@ def cleanup():
def closeall():
if verbose: log('closecall')
for conn in conns:
if verbose: syslog.syslog(syslog.LOG_ERR, 'closecall')
for conn in conns:
conns[conn].close()
def daemonize(working_dir="/", stdin='/dev/zero', stdout='/dev/null', stderr='/dev/null'):
"""
Does the UNIX double-fork magic, see Stevens' "Advanced Programming in the
UNIX Environment" for details (ISBN 0201563177)
http://www.yendor.com/programming/unix/apue/proc/fork2.c
"""
try:
# first fork
pid = os.fork()
if pid > 0:
# exit from first parent
os._exit(0)
except OSError, e:
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
os._exit(1)
# decouple from parent environment
os.chdir(working_dir)
os.setsid()
os.umask(0)
# second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
os._exit(0)
except OSError, e:
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# redirects standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = file(stdin, 'r')
so = file(stdout, 'a+')
se = file(stderr, 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
msgonly=False
helpflag=False
verbose=False
fdaemon=False
daemonized = False
optlist=[]
args=[]
msgboot={}
@@ -368,9 +380,9 @@ cmdargs = []
try:
optlist, args = getopt.getopt(sys.argv[1:], 'bc:dhm:v')
optlist, args = getopt.getopt(sys.argv[1:], 'bc:dhm:v')
except:
helpflag=True
helpflag=True
for o,a in optlist:
if o == '-b':
@@ -442,7 +454,7 @@ if f:
if r[0] == 'hb_hosts':
hb_hosts=eval(r[1])
if verbose:
print "notice: cfg hb_hosts: %s" % hb_hosts
print "notice: cfg hb_hosts: %s" % hb_hosts
elif r[0] == 'interval':
interval=eval(r[1])
elif r[0] == 'hb_port':
@@ -487,7 +499,7 @@ if verbose:
if len(msgboot) > 0:
if verbose: print "on boot"
msgboot['acks'] = 0
msgboot['acks'] = 0
for conn in conns:
conns[conn].sendto(msgboot)
@@ -497,63 +509,20 @@ if msgonly:
sys.exit(0)
#
syslog.openlog('hbc', syslog.LOG_PID, syslog.LOG_DAEMON)
if fdaemon:
print "daemoinizing."
daemonize()
daemonized = True
syslog.syslog(syslog.LOG_ERR, 'starting heartbeat to %s' % ','.join(hb_hosts))
pidfile = daemon.pidfile.TimeoutPIDLockFile(PIDFILE, acquire_timeout=-1)
try:
opid = pidfile.read_pid()
except:
opid = None
running = True
try:
process()
except:
syslogtrace('process')
if verbose: print "err: process exit: %s" % e
if opid:
try:
os.kill(opid, 0)
is_running = True
except:
is_running = False
if verbose: print "is_running %s" % is_running
if is_running:
print "process still alive %s" % opid
sys.exit(1)
print "warning: stale pid file removed"
os.unlink(PIDFILE)
print "daemoinizing... %s" % os.getpid()
context = daemon.DaemonContext(
working_directory='/tmp',
umask=0o022,
pidfile=pidfile,
detach_process=True,
# initgroups=False,
)
context.signal_map = {
# signal.SIGHUP: cleanup,
signal.SIGTERM: 'terminate',
# signal.SIGUSR1: reload_program_config,
}
context.files_preserve = []
for conn in conns:
context.files_preserve += [conns[conn].sock, conns[conn].sock.fileno()]
with context:
log('starting heartbeat to %s' % ','.join(hb_hosts))
running = True
try:
process()
except:
syslogtrace('process')
else:
running = True
try:
if verbose: print "starting loop process"
process()
except Exception as e:
if verbose: print "err: process exit: %s" % e
syslogtrace('process')
if verbose: log( "main: cleanup")
cleanup()
if dorestart: