willsh1997's picture
:wrench: remove codecarbon install, add slightly modified codecarbon pkg to repo
deb7c43
Raw
History Blame Contribute Delete
2.79 kB
"""
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