diff --git a/src/libprs500/gui2/main.py b/src/libprs500/gui2/main.py index 2057443e61..f88cc133f4 100644 --- a/src/libprs500/gui2/main.py +++ b/src/libprs500/gui2/main.py @@ -43,6 +43,8 @@ from libprs500.gui2.dialogs.lrf_single import LRFSingleDialog from libprs500.gui2.dialogs.password import PasswordDialog from libprs500.gui2.lrf_renderer.main import file_renderer from libprs500.gui2.lrf_renderer.main import option_parser as lrfviewerop +from libprs500.library.database import DatabaseLocked + class Main(MainWindow, Ui_MainWindow): @@ -715,7 +717,12 @@ def main(args=sys.argv): QCoreApplication.setOrganizationName(ORG_NAME) QCoreApplication.setApplicationName(APP_UID) initialize_file_icon_provider() - main = Main() + try: + main = Main() + except DatabaseLocked, err: + QMessageBox.critical(None, 'Cannot Start '+__appname__, + 'Another program is using the database. Perhaps %s is already running?'%(__appname__,)) + return 1 sys.excepthook = main.unhandled_exception return app.exec_() return 0 diff --git a/src/libprs500/library/database.py b/src/libprs500/library/database.py index c7323807d1..23a26136cb 100644 --- a/src/libprs500/library/database.py +++ b/src/libprs500/library/database.py @@ -35,9 +35,42 @@ class Concatenate(object): return self.ans[:-len(self.sep)] return self.ans +_lock_file = None +class DatabaseLocked(Exception): + pass + +def _lock(path): + path = os.path.join(os.path.dirname(path), '.'+os.path.basename(path)+'.lock') + global _lock_file + if _lock_file is not None: + raise DatabaseLocked('Database already locked in this instance.') + try: + _lock_file = open(path, 'wb') + except IOError: + raise DatabaseLocked('Database in use by another instance') + try: + import fcntl, errno + try: + fcntl.lockf(_lock_file.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB) + except IOError, err: + _lock_file = None + if err.errno in (errno.EACCES, errno.EAGAIN): + raise DatabaseLocked('Database in use by another instance') + except ImportError: + try: + import msvcrt + try: + msvcrt.locking(_lock_file.fileno(), msvcrt.LK_NBLCK, 1) + except IOError: + _lock_file = None + raise DatabaseLocked('Database in use by another instance') + except ImportError: + pass + def _connect(path): if isinstance(path, unicode): path = path.encode('utf-8') + _lock(path) conn = sqlite.connect(path, detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES) conn.row_factory = lambda cursor, row : list(row) conn.create_aggregate('concat', 1, Concatenate) @@ -621,6 +654,12 @@ class LibraryDatabase(object): conn.execute('pragma user_version=2') conn.commit() + def __del__(self): + global _lock_file + import os + if _lock_file is not None and os.path.exists(_lock_file): + os.unlink(_lock_file) + def __init__(self, dbpath): self.dbpath = dbpath self.conn = _connect(dbpath)