|
Server : Apache System : Linux ecngx264.inmotionhosting.com 4.18.0-553.77.1.lve.el8.x86_64 #1 SMP Wed Oct 8 14:21:00 UTC 2025 x86_64 User : lonias5 ( 3576) PHP Version : 7.3.33 Disable Function : NONE Directory : /usr/lib/imh-whmapi/venv/lib/python3.13/site-packages/rads/ |
Upload File : |
"""Functions for acquiring a process lock"""
import socket
import hashlib
import contextlib
import time
import __main__ as main_obj
class LockError(Exception):
"""Raised when a rads.lock cannot be acquired"""
__module__ = 'rads'
@contextlib.contextmanager
def lock(name: str | None = None):
"""Context manager to create an abstract UNIX socket which will behave as
a "lock". This can be used en lieu of /var/run file pids/locks to determine
if an instance of a process is already running and ensure the lock is not
left behind if the process terminates prematurely
Args:
name: unique name of the lock; defaults to filename of ``__main__``
Raises:
LockError: if the "lock" already existed
"""
if name is None:
# caveat: this will raise AttributeError
# if run in an interactive python shell
name = main_obj.__file__
name = name.encode('utf-8')
lock_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
try:
lock_socket.bind(f'\0{hashlib.sha256(name).hexdigest()}')
except OSError as exc:
raise LockError(name) from exc
try:
yield
finally:
lock_socket.close()
lock.__module__ = 'rads'
@contextlib.contextmanager
def wait_lock(
name: str | None = None,
sleep: float = 0.2,
max_sleep: int | None = None,
):
"""Context manager to wait until a rads.lock() can be acquired, and do so
Args:
name: unique name of the lock; defaults to filename of ``__main__``
sleep: secs before trying to acquire the lock again
max_sleep: max number of tries to acquire the lock
Raises:
LockError: if max_sleep is exceeded
"""
slept = 0.0
while True:
try:
with lock(name):
yield
return
except LockError:
time.sleep(sleep)
slept += sleep
if max_sleep is not None and slept >= max_sleep:
raise
wait_lock.__module__ = 'rads'