Daemonising fixes

- change forking exit order as systemd expects (wait until child is
ready, then exit parent, then grandparent)
- fix signal handler if prctl not installed
- revert recent PID file changes
This commit is contained in:
Peter Šurda 2018-01-01 13:08:12 +01:00
parent baba0ae206
commit d9a4263083
Signed by untrusted user: PeterSurda
GPG Key ID: 0C5F50C0B5F37D87
3 changed files with 32 additions and 7 deletions

View File

@ -342,13 +342,21 @@ class Main:
sleep(1)
def daemonize(self):
grandfatherPid = os.getpid()
parentPid = None
try:
if os.fork():
# unlock
shared.thisapp.cleanup()
# wait until grandchild ready
while True:
sleep(1)
os._exit(0)
except AttributeError:
# fork not implemented
pass
else:
parentPid = os.getpid()
shared.thisapp.lock() # relock
os.umask(0)
try:
@ -358,12 +366,17 @@ class Main:
pass
try:
if os.fork():
# unlock
shared.thisapp.cleanup()
# wait until child ready
while True:
sleep(1)
os._exit(0)
except AttributeError:
# fork not implemented
pass
else:
shared.thisapp.lock(True) # relock and write pid
shared.thisapp.lock() # relock
shared.thisapp.lockPid = None # indicate we're the final child
sys.stdout.flush()
sys.stderr.flush()
@ -374,6 +387,10 @@ class Main:
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
if parentPid:
# signal ready
os.kill(parentPid, signal.SIGTERM)
os.kill(grandfatherPid, signal.SIGTERM)
def setSignalHandler(self):
signal.signal(signal.SIGINT, helper_generic.signal_handler)

View File

@ -51,7 +51,7 @@ def signal_handler(signal, frame):
raise SystemExit
if "PoolWorker" in current_process().name:
raise SystemExit
if current_thread().name != "PyBitmessage":
if current_thread().name not in ("PyBitmessage", "MainThread"):
return
logger.error("Got signal %i", signal)
if BMConfigParser().safeGetBoolean('bitmessagesettings', 'daemon'):

View File

@ -36,7 +36,7 @@ class singleinstance:
self.initialized = True
atexit.register(self.cleanup)
def lock(self, writePid = False):
def lock(self):
if self.lockPid is None:
self.lockPid = os.getpid()
if sys.platform == 'win32':
@ -68,16 +68,24 @@ class singleinstance:
sys.exit(-1)
else:
pidLine = "%i\n" % self.lockPid
if writePid:
self.fp.truncate(0)
self.fp.write(pidLine)
self.fp.flush()
self.fp.truncate(0)
self.fp.write(pidLine)
self.fp.flush()
def cleanup(self):
if not self.initialized:
return
if self.daemon and self.lockPid == os.getpid():
# these are the two initial forks while daemonizing
try:
if sys.platform == 'win32':
if hasattr(self, 'fd'):
os.close(self.fd)
else:
fcntl.lockf(self.fp, fcntl.LOCK_UN)
except Exception, e:
pass
return
print "Cleaning up lockfile"
try: