Spaces:
Sleeping
Sleeping
| """ | |
| Ensures that only one instance of codecarbon is running at a time. | |
| It creates a lock file in /tmp/.codecarbon.lock and removes it on exit. | |
| If the lock file already exists, it exits the program. | |
| """ | |
| import atexit | |
| import errno | |
| import os | |
| import signal | |
| import tempfile | |
| import threading | |
| from codecarbon.external.logger import logger | |
| # We use tempfile.gettempdir() to get the system's temporary directory (linux: /tmp, windows: C:\Users\username\AppData\Local\Temp) | |
| LOCKFILE = os.path.join(tempfile.gettempdir(), ".codecarbon.lock") | |
| class Lock: | |
| """A lock to ensure only one instance of codecarbon is running.""" | |
| def __init__(self): | |
| self._has_created_lock = False | |
| self.lockfile_path = LOCKFILE | |
| atexit.register( | |
| self.release | |
| ) # Ensure release() is called on unexpected exit of the user's python code | |
| # If there is more than one thread add a lock | |
| self._thread_lock = threading.Lock() | |
| # If the current thread is the main thread, register signal handlers | |
| if threading.current_thread() is threading.main_thread(): | |
| # Register signal handlers to ensure lock release on interruption | |
| signal.signal(signal.SIGINT, self._handle_exit) # Ctrl+C | |
| signal.signal(signal.SIGTERM, self._handle_exit) # Termination signal | |
| def _handle_exit(self, signum, frame): | |
| """Ensures the lock file is removed when the script is interrupted.""" | |
| logger.debug(f"Signal {signum} received. Releasing lock and exiting.") | |
| self.release() | |
| raise SystemExit(1) # Exit gracefully to prevent further execution | |
| def acquire(self): | |
| """Creates a lock file and ensures it's the only instance running.""" | |
| with self._thread_lock: | |
| # Attempt to create the lock file | |
| try: | |
| with open(LOCKFILE, "x") as _: | |
| logger.debug(f"Lock file created. Path: {LOCKFILE}") | |
| self._has_created_lock = True | |
| except FileExistsError: | |
| logger.debug( | |
| f"Lock file {LOCKFILE} already exists. This usually means another instance of codecarbon is running. You can safely delete it if you want or use allow_multiple_runs parameter to always bypass it." | |
| ) | |
| raise | |
| def release(self): | |
| """Removes the lock file on exit.""" | |
| with self._thread_lock: | |
| logger.debug("Removing the lock") | |
| try: | |
| # Remove the lock file only if it was created by this instance | |
| if self._has_created_lock: | |
| os.remove(LOCKFILE) | |
| except OSError as e: | |
| logger.debug(f"Error: {e}") | |
| if e.errno != errno.ENOENT: | |
| raise | |