From 24a2deed8f0a21780ba2ea9752be84ebf8bb7c36 Mon Sep 17 00:00:00 2001 From: mailchuck Date: Tue, 26 Jan 2016 13:01:28 +0100 Subject: [PATCH] Cleanup lockfile on exit singleton.py design was broken. Fixed Bitmessage#775 --- src/bitmessagemain.py | 4 +--- src/bitmessageqt/__init__.py | 1 + src/shared.py | 4 +++- src/singleton.py | 24 ++++++++++++++---------- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index 81b8613e..135d835f 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -152,13 +152,11 @@ if shared.useVeryEasyProofOfWorkForTesting: class Main: def start(self, daemon=False): - global thisapp - _fixWinsock() shared.daemon = daemon # is the application already running? If yes then exit. - thisapp = singleton.singleinstance("", daemon) + shared.thisapp = singleton.singleinstance("", daemon) # get curses flag curses = False diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 41540fa9..a635a7da 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -2842,6 +2842,7 @@ class MyForm(settingsmixin.SMainWindow): self.statusBar().showMessage(_translate( "MainWindow", "All done. Closing user interface...")) + shared.thisapp.cleanup() os._exit(0) # window close event diff --git a/src/shared.py b/src/shared.py index d342ddaa..f18b4066 100644 --- a/src/shared.py +++ b/src/shared.py @@ -55,6 +55,7 @@ appdata = '' #holds the location of the application data storage directory statusIconColor = 'red' connectedHostsList = {} #List of hosts to which we are connected. Used to guarantee that the outgoingSynSender threads won't connect to the same remote node twice. shutdown = 0 #Set to 1 by the doCleanShutdown function. Used to tell the proof of work worker threads to exit. +thisapp = None # singleton lock instance alreadyAttemptedConnectionsList = { } # This is a list of nodes to which we have already attempted a connection alreadyAttemptedConnectionsListLock = threading.Lock() @@ -392,7 +393,7 @@ def isProofOfWorkSufficient(data, return POW <= 2 ** 64 / (nonceTrialsPerByte*(len(data) + payloadLengthExtraBytes + ((TTL*(len(data)+payloadLengthExtraBytes))/(2 ** 16)))) def doCleanShutdown(): - global shutdown + global shutdown, thisapp shutdown = 1 #Used to tell proof of work worker threads and the objectProcessorThread to exit. broadcastToSendDataQueues((0, 'shutdown', 'no data')) objectProcessorQueue.put(('checkShutdownVariable', 'no data')) @@ -440,6 +441,7 @@ def doCleanShutdown(): if safeConfigGetBoolean('bitmessagesettings','daemon'): logger.info('Clean shutdown complete.') + thisapp.cleanup() os._exit(0) # If you want to command all of the sendDataThreads to do something, like shutdown or send some data, this diff --git a/src/singleton.py b/src/singleton.py index f3124424..a4b6c678 100644 --- a/src/singleton.py +++ b/src/singleton.py @@ -1,10 +1,16 @@ #! /usr/bin/env python -import sys -import os +import atexit import errno -import shared from multiprocessing import Process +import os +import sys +import shared + +try: + import fcntl # @UnresolvedImport +except: + pass class singleinstance: """ @@ -14,9 +20,8 @@ class singleinstance: which is under the Python Software Foundation License version 2 """ def __init__(self, flavor_id="", daemon=False): - import sys self.initialized = False - self.daemon = daemon; + self.daemon = daemon self.lockfile = os.path.normpath(os.path.join(shared.appdata, 'singleton%s.lock' % flavor_id)) if not self.daemon: @@ -38,7 +43,6 @@ class singleinstance: print(e.errno) raise else: # non Windows - import fcntl # @UnresolvedImport self.fp = open(self.lockfile, 'w') try: fcntl.lockf(self.fp, fcntl.LOCK_EX | fcntl.LOCK_NB) @@ -46,20 +50,20 @@ class singleinstance: print 'Another instance of this application is already running' sys.exit(-1) self.initialized = True + atexit.register(self.cleanup) - def __del__(self): - import sys + def cleanup(self): if not self.initialized: return + print "Cleaning up lockfile" try: if sys.platform == 'win32': if hasattr(self, 'fd'): os.close(self.fd) os.unlink(self.lockfile) else: - import fcntl # @UnresolvedImport fcntl.lockf(self.fp, fcntl.LOCK_UN) if os.path.isfile(self.lockfile): os.unlink(self.lockfile) except Exception, e: - sys.exit(-1) + pass