mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-06-05 09:53:33 +03:00
Move journal locking code into new monitor.JournalLock class
This commit is contained in:
parent
872f380831
commit
c0e7be98f8
@ -10,7 +10,6 @@ import sys
|
|||||||
import webbrowser
|
import webbrowser
|
||||||
from builtins import object, str
|
from builtins import object, str
|
||||||
from os import chdir, environ
|
from os import chdir, environ
|
||||||
from os import getpid as os_getpid
|
|
||||||
from os.path import dirname, isdir, join
|
from os.path import dirname, isdir, join
|
||||||
from sys import platform
|
from sys import platform
|
||||||
from time import localtime, strftime, time
|
from time import localtime, strftime, time
|
||||||
@ -34,6 +33,7 @@ if __name__ == '__main__':
|
|||||||
# After the redirect in case config does logging setup
|
# After the redirect in case config does logging setup
|
||||||
from config import appversion, appversion_nobuild, config, copyright
|
from config import appversion, appversion_nobuild, config, copyright
|
||||||
from EDMCLogging import edmclogger, logger, logging
|
from EDMCLogging import edmclogger, logger, logging
|
||||||
|
from monitor import JournalLock
|
||||||
|
|
||||||
if __name__ == '__main__': # noqa: C901
|
if __name__ == '__main__': # noqa: C901
|
||||||
# Command-line arguments
|
# Command-line arguments
|
||||||
@ -79,23 +79,11 @@ if __name__ == '__main__': # noqa: C901
|
|||||||
"""
|
"""
|
||||||
logger.trace('Begin...')
|
logger.trace('Begin...')
|
||||||
|
|
||||||
|
locked = journal_lock.journaldir_obtain_lock()
|
||||||
|
|
||||||
if platform == 'win32':
|
if platform == 'win32':
|
||||||
logger.trace('win32, using msvcrt')
|
|
||||||
# win32 doesn't have fcntl, so we have to use msvcrt
|
|
||||||
import msvcrt
|
|
||||||
|
|
||||||
logger.trace(f'journal_dir_lockfile = {journal_dir_lockfile!r}')
|
if not locked:
|
||||||
|
|
||||||
locked = False
|
|
||||||
try:
|
|
||||||
msvcrt.locking(journal_dir_lockfile.fileno(), msvcrt.LK_NBLCK, 4096)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.info(f"Exception: Couldn't lock journal directory \"{journal_dir}\""
|
|
||||||
f", assuming another process running: {e!r}")
|
|
||||||
locked = True
|
|
||||||
|
|
||||||
if locked:
|
|
||||||
# Need to do the check for this being an edmc:// auth callback
|
# Need to do the check for this being an edmc:// auth callback
|
||||||
import ctypes
|
import ctypes
|
||||||
from ctypes.wintypes import BOOL, HWND, INT, LPARAM, LPCWSTR, LPWSTR
|
from ctypes.wintypes import BOOL, HWND, INT, LPARAM, LPCWSTR, LPWSTR
|
||||||
@ -177,28 +165,6 @@ if __name__ == '__main__': # noqa: C901
|
|||||||
|
|
||||||
return False # Another instance is running
|
return False # Another instance is running
|
||||||
|
|
||||||
else:
|
|
||||||
logger.trace('NOT win32, using fcntl')
|
|
||||||
try:
|
|
||||||
import fcntl
|
|
||||||
|
|
||||||
except ImportError:
|
|
||||||
logger.warning("Not on win32 and we have no fcntl, can't use a file lock!"
|
|
||||||
"Allowing multiple instances!")
|
|
||||||
return True # Lie about there being no other instances
|
|
||||||
|
|
||||||
try:
|
|
||||||
fcntl.flock(journal_dir_lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.info(f"Exception: Couldn't lock journal directory \"{journal_dir}\","
|
|
||||||
f"assuming another process running: {e!r}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
journal_dir_lockfile.write(f"Path: {journal_dir}\nPID: {os_getpid()}\n")
|
|
||||||
journal_dir_lockfile.flush()
|
|
||||||
|
|
||||||
logger.trace('Done')
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def already_running_popup():
|
def already_running_popup():
|
||||||
@ -224,20 +190,9 @@ if __name__ == '__main__': # noqa: C901
|
|||||||
|
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
|
|
||||||
journal_dir: str = config.get('journaldir') or config.default_journal_dir
|
journal_lock = JournalLock()
|
||||||
# This must be at top level to guarantee the file handle doesn't go out
|
|
||||||
# of scope and get cleaned up, removing the lock with it.
|
|
||||||
journal_dir_lockfile_name = join(journal_dir, 'edmc-journal-lock.txt')
|
|
||||||
try:
|
|
||||||
journal_dir_lockfile = open(journal_dir_lockfile_name, mode='w+', encoding='utf-8')
|
|
||||||
|
|
||||||
# Linux CIFS read-only mount throws: OSError(30, 'Read-only file system')
|
if journal_lock.journal_dir_lockfile:
|
||||||
# Linux no-write-perm directory throws: PermissionError(13, 'Permission denied')
|
|
||||||
except Exception as e: # For remote FS this could be any of a wide range of exceptions
|
|
||||||
logger.warning(f"Couldn't open \"{journal_dir_lockfile_name}\" for \"w+\""
|
|
||||||
f" Aborting duplicate process checks: {e!r}")
|
|
||||||
|
|
||||||
else:
|
|
||||||
if not no_other_instance_running():
|
if not no_other_instance_running():
|
||||||
# There's a copy already running.
|
# There's a copy already running.
|
||||||
|
|
||||||
|
69
monitor.py
69
monitor.py
@ -2,6 +2,7 @@ from collections import defaultdict, OrderedDict
|
|||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import threading
|
import threading
|
||||||
|
from os import getpid as os_getpid
|
||||||
from os import listdir, SEEK_SET, SEEK_END
|
from os import listdir, SEEK_SET, SEEK_END
|
||||||
from os.path import basename, expanduser, isdir, join
|
from os.path import basename, expanduser, isdir, join
|
||||||
from sys import platform
|
from sys import platform
|
||||||
@ -1021,3 +1022,71 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
|||||||
|
|
||||||
# singleton
|
# singleton
|
||||||
monitor = EDLogs()
|
monitor = EDLogs()
|
||||||
|
|
||||||
|
|
||||||
|
class JournalLock:
|
||||||
|
"""Handle locking of journal directory."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""Initialise where the journal directory and lock file are."""
|
||||||
|
self.journal_dir: str = config.get('journaldir') or config.default_journal_dir
|
||||||
|
self.journal_dir_lock = None
|
||||||
|
|
||||||
|
self.journal_dir_lockfile_name: str = join(self.journal_dir, 'edmc-journal-lock.txt')
|
||||||
|
try:
|
||||||
|
self.journal_dir_lockfile = open(self.journal_dir_lockfile_name, mode='w+', encoding='utf-8')
|
||||||
|
|
||||||
|
# Linux CIFS read-only mount throws: OSError(30, 'Read-only file system')
|
||||||
|
# Linux no-write-perm directory throws: PermissionError(13, 'Permission denied')
|
||||||
|
except Exception as e: # For remote FS this could be any of a wide range of exceptions
|
||||||
|
logger.warning(f"Couldn't open \"{self.journal_dir_lockfile_name}\" for \"w+\""
|
||||||
|
f" Aborting duplicate process checks: {e!r}")
|
||||||
|
|
||||||
|
def journaldir_obtain_lock(self) -> bool:
|
||||||
|
"""
|
||||||
|
Attempt to obtain a lock on the journal directory.
|
||||||
|
|
||||||
|
:return: bool - True if we successfully obtained the lock
|
||||||
|
"""
|
||||||
|
logger.trace(f'journal_dir_lockfile = {self.journal_dir_lockfile!r}')
|
||||||
|
|
||||||
|
if platform == 'win32':
|
||||||
|
logger.trace('win32, using msvcrt')
|
||||||
|
# win32 doesn't have fcntl, so we have to use msvcrt
|
||||||
|
import msvcrt
|
||||||
|
|
||||||
|
try:
|
||||||
|
msvcrt.locking(self.journal_dir_lockfile.fileno(), msvcrt.LK_NBLCK, 4096)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(f"Exception: Couldn't lock journal directory \"{self.journal_dir}\""
|
||||||
|
f", assuming another process running: {e!r}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
else:
|
||||||
|
logger.trace('NOT win32, using fcntl')
|
||||||
|
try:
|
||||||
|
import fcntl
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
logger.warning("Not on win32 and we have no fcntl, can't use a file lock!"
|
||||||
|
"Allowing multiple instances!")
|
||||||
|
return True # Lie about being locked
|
||||||
|
|
||||||
|
try:
|
||||||
|
fcntl.flock(self.journal_dir_lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(f"Exception: Couldn't lock journal directory \"{self.journal_dir}\","
|
||||||
|
f"assuming another process running: {e!r}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.journal_dir_lockfile.write(f"Path: {self.journal_dir}\nPID: {os_getpid()}\n")
|
||||||
|
self.journal_dir_lockfile.flush()
|
||||||
|
|
||||||
|
logger.trace('Done')
|
||||||
|
return True
|
||||||
|
|
||||||
|
def journaldir_release_lock(self) -> bool:
|
||||||
|
"""Release lock on journal directory."""
|
||||||
|
pass
|
||||||
|
Loading…
x
Reference in New Issue
Block a user