mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-05-31 23:59:38 +03:00
Change JournalLock.obtain_lock() return to an Enum.
This way we can tell the difference between: 1. This process obtained the lock. 2. Another process has the lock. 3. We couldn't get the lock due to not being able to open the lock file read-write. Case 3 is currently also returned if the configured journal directory doesn't exist. This will be the case on any MacOS system that never had the game running. Likely given the OS hasn't been supported for the game in years now.
This commit is contained in:
parent
e76e76bbe4
commit
60c67723ca
@ -33,7 +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 journal_lock import JournalLock
|
from journal_lock import JournalLock, JournalLockResult
|
||||||
|
|
||||||
if __name__ == '__main__': # noqa: C901
|
if __name__ == '__main__': # noqa: C901
|
||||||
# Command-line arguments
|
# Command-line arguments
|
||||||
@ -72,16 +72,14 @@ if __name__ == '__main__': # noqa: C901
|
|||||||
config.set_auth_force_localserver()
|
config.set_auth_force_localserver()
|
||||||
|
|
||||||
def handle_edmc_callback_or_foregrounding(): # noqa: CCR001
|
def handle_edmc_callback_or_foregrounding(): # noqa: CCR001
|
||||||
"""
|
"""Handle any edmc:// auth callback, else foreground existing window."""
|
||||||
Handle any edmc:// auth callback, else foreground existing window.
|
|
||||||
"""
|
|
||||||
logger.trace('Begin...')
|
logger.trace('Begin...')
|
||||||
|
|
||||||
if platform == 'win32':
|
if platform == 'win32':
|
||||||
|
|
||||||
# If *this* instance hasn't locked, then another already has and we
|
# If *this* instance hasn't locked, then another already has and we
|
||||||
# now need to do the edmc:// checks for auth callback
|
# now need to do the edmc:// checks for auth callback
|
||||||
if not locked:
|
if locked != JournalLockResult.LOCKED:
|
||||||
import ctypes
|
import ctypes
|
||||||
from ctypes.wintypes import BOOL, HWND, INT, LPARAM, LPCWSTR, LPWSTR
|
from ctypes.wintypes import BOOL, HWND, INT, LPARAM, LPCWSTR, LPWSTR
|
||||||
|
|
||||||
@ -190,7 +188,7 @@ if __name__ == '__main__': # noqa: C901
|
|||||||
|
|
||||||
handle_edmc_callback_or_foregrounding()
|
handle_edmc_callback_or_foregrounding()
|
||||||
|
|
||||||
if not locked:
|
if locked == JournalLockResult.ALREADY_LOCKED:
|
||||||
# There's a copy already running.
|
# There's a copy already running.
|
||||||
|
|
||||||
logger.info("An EDMarketConnector.exe process was already running, exiting.")
|
logger.info("An EDMarketConnector.exe process was already running, exiting.")
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import pathlib
|
import pathlib
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
|
from enum import Enum
|
||||||
from os import getpid as os_getpid
|
from os import getpid as os_getpid
|
||||||
from sys import platform
|
from sys import platform
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
@ -17,6 +18,15 @@ if TYPE_CHECKING:
|
|||||||
return x
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
class JournalLockResult(Enum):
|
||||||
|
"""Enumeration of possible outcomes of trying to lock the Journal Directory."""
|
||||||
|
|
||||||
|
LOCKED = 1
|
||||||
|
JOURNALDIR_NOTEXIST = 2
|
||||||
|
JOURNALDIR_READONLY = 3
|
||||||
|
ALREADY_LOCKED = 4
|
||||||
|
|
||||||
|
|
||||||
class JournalLock:
|
class JournalLock:
|
||||||
"""Handle locking of journal directory."""
|
"""Handle locking of journal directory."""
|
||||||
|
|
||||||
@ -28,11 +38,11 @@ class JournalLock:
|
|||||||
# We never test truthiness of this, so let it be defined when first assigned. Avoids type hint issues.
|
# We never test truthiness of this, so let it be defined when first assigned. Avoids type hint issues.
|
||||||
# self.journal_dir_lockfile: Optional[IO] = None
|
# self.journal_dir_lockfile: Optional[IO] = None
|
||||||
|
|
||||||
def obtain_lock(self) -> bool:
|
def obtain_lock(self) -> JournalLockResult:
|
||||||
"""
|
"""
|
||||||
Attempt to obtain a lock on the journal directory.
|
Attempt to obtain a lock on the journal directory.
|
||||||
|
|
||||||
:return: bool - True if we successfully obtained the lock
|
:return: LockResult - See the class Enum definition
|
||||||
"""
|
"""
|
||||||
self.journal_dir_lockfile_name = self.journal_dir_path / 'edmc-journal-lock.txt'
|
self.journal_dir_lockfile_name = self.journal_dir_path / 'edmc-journal-lock.txt'
|
||||||
logger.trace(f'journal_dir_lockfile_name = {self.journal_dir_lockfile_name!r}')
|
logger.trace(f'journal_dir_lockfile_name = {self.journal_dir_lockfile_name!r}')
|
||||||
@ -44,7 +54,7 @@ class JournalLock:
|
|||||||
except Exception as e: # For remote FS this could be any of a wide range of exceptions
|
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+\""
|
logger.warning(f"Couldn't open \"{self.journal_dir_lockfile_name}\" for \"w+\""
|
||||||
f" Aborting duplicate process checks: {e!r}")
|
f" Aborting duplicate process checks: {e!r}")
|
||||||
return False
|
return JournalLockResult.JOURNALDIR_READONLY
|
||||||
|
|
||||||
if platform == 'win32':
|
if platform == 'win32':
|
||||||
logger.trace('win32, using msvcrt')
|
logger.trace('win32, using msvcrt')
|
||||||
@ -57,7 +67,7 @@ class JournalLock:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.info(f"Exception: Couldn't lock journal directory \"{self.journal_dir}\""
|
logger.info(f"Exception: Couldn't lock journal directory \"{self.journal_dir}\""
|
||||||
f", assuming another process running: {e!r}")
|
f", assuming another process running: {e!r}")
|
||||||
return False
|
return JournalLockResult.ALREADY_LOCKED
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.trace('NOT win32, using fcntl')
|
logger.trace('NOT win32, using fcntl')
|
||||||
@ -67,7 +77,7 @@ class JournalLock:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
logger.warning("Not on win32 and we have no fcntl, can't use a file lock!"
|
logger.warning("Not on win32 and we have no fcntl, can't use a file lock!"
|
||||||
"Allowing multiple instances!")
|
"Allowing multiple instances!")
|
||||||
return True # Lie about being locked
|
return JournalLockResult.LOCKED
|
||||||
|
|
||||||
try:
|
try:
|
||||||
fcntl.flock(self.journal_dir_lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
fcntl.flock(self.journal_dir_lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||||
@ -75,13 +85,13 @@ class JournalLock:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.info(f"Exception: Couldn't lock journal directory \"{self.journal_dir}\", "
|
logger.info(f"Exception: Couldn't lock journal directory \"{self.journal_dir}\", "
|
||||||
f"assuming another process running: {e!r}")
|
f"assuming another process running: {e!r}")
|
||||||
return False
|
return JournalLockResult.ALREADY_LOCKED
|
||||||
|
|
||||||
self.journal_dir_lockfile.write(f"Path: {self.journal_dir}\nPID: {os_getpid()}\n")
|
self.journal_dir_lockfile.write(f"Path: {self.journal_dir}\nPID: {os_getpid()}\n")
|
||||||
self.journal_dir_lockfile.flush()
|
self.journal_dir_lockfile.flush()
|
||||||
|
|
||||||
logger.trace('Done')
|
logger.trace('Done')
|
||||||
return True
|
return JournalLockResult.LOCKED
|
||||||
|
|
||||||
def release_lock(self) -> bool:
|
def release_lock(self) -> bool:
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user