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

View File

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

View File

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