Skip to main content

Systemwide pseudo-atomic lock mechanism for Python

Project description

CryoLock

The advisory file lock mechanism for the paranoid; designed to work under restrictive environments.

CryoLock is a library for file-based locking of critical sections. It's primarily developed for applications that make changes to critical files as it ensures that two instances of the same application won't interfere with one another or corrupt said critical files. A CryoLock is essentially Python's threading.Lock and multiprocessing.Lock but for threads and processes that can't interact with each other and therefore can't be provided with a shared lock instance.

  • Completely systemwide. Can be used to enforce mutual exclusion even if the processes trying to acquire the lock are completely independent from one another.
  • Cross-platform. Works in any environment where the required functions are available in the Python standard library (namely os.urandom and os.utime).
  • Logically atomic. Given proper configuration, there are no race conditions that could allow multiple parallel threads to acquire the same lock; even if the underlying OS doesn't offer any atomic FS operations.
  • Portable. Written in pure Python and without any external dependencies.
  • Anywhere. Supports Python 2.7 as well as Python 3.

Usage

Executing help(__import__('cryolock')) in a Python console should provide some documentation; but here are some templates:

"""Simple example."""

import os
from cryolock import Lock

# Do normal stuff here...

with Lock(os.path.join(os.getcwd(), 'my-simple-lock.cryolock')):
    # Do critical stuff here...

# Continue doing normal stuff here...
"""Example with a reentrant lock."""

import os
from cryolock import Lock, RLock

def foo(lock = None):
    if lock is None:
        lock = Lock(os.path.join(os.getcwd(), 'my-simple-lock.cryolock'))

    # Do normal stuff here...

    with lock:
        # Do critical stuff here...

    # Continue doing normal stuff here...

def bar(recursive_lock = None):
    if recursive_lock is None:
        recursive_lock = RLock(os.path.join(os.getcwd(), 'my-simple-lock.cryolock'))

    # Do normal stuff here...

    with recursive_lock:
        # Do critical stuff here...

        foo(recursive_lock)

        # Do more critical stuff here...

    # Continue doing normal stuff here...

foo()
bar()


def this_would_have_raised_a_runtime_error():
    # Do normal stuff here...

    lock = Lock(os.path.join(os.getcwd(), 'my-simple-lock.cryolock'))

    with lock:
        # Do critical stuff here...

        foo(lock)

        # Do more critical stuff here...

    # Continue doing normal stuff here...

def this_would_have_caused_a_deadlock():
    # Do normal stuff here...

    with RLock(os.path.join(os.getcwd(), 'my-simple-lock.cryolock')):
        # Do critical stuff here...

        foo()

        # Do more critical stuff here...

    # Continue doing normal stuff here...
"""Example with a `cryolock.Lock` instance being shared between multiple threads."""

import os
from cryolock import Lock as FSLock
from threading import Lock as ThreadLock, Thread

def thread_function(thread_lock, fs_lock):
    # Do normal stuff here...

    # An acquired `cryolock.Lock` instance EXCLUSIVELY stops OTHER `cryolock.Lock` instances from accessing a
    # critical region; so utilizing a `threading.Lock` is required if you're gonna be sharing a `cryolock.Lock`
    # instance between multiple threads.
    with thread_lock:
        with fs_lock:
            # Do critical stuff here...

    # Continue doing normal stuff here...

tl = ThreadLock()
fsl = FSLock(os.path.join(os.getcwd(), 'my-shared-lock.cryolock'))
for _ in range(5):
    Thread(target=thread_function, args=(tl, fsl))

Cloning and Contributing

This repository can be cloned and accepts issues and pull requests:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cryolock-1.2.0.tar.gz (22.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cryolock-1.2.0-py2.py3-none-any.whl (22.8 kB view details)

Uploaded Python 2Python 3

File details

Details for the file cryolock-1.2.0.tar.gz.

File metadata

  • Download URL: cryolock-1.2.0.tar.gz
  • Upload date:
  • Size: 22.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.32.5

File hashes

Hashes for cryolock-1.2.0.tar.gz
Algorithm Hash digest
SHA256 c7917e8ad942de76c5fb81a392b01cda864ea2812626a2c15e6d83a86fa2f7ed
MD5 059103fd37058e4bc02d2cf52d7b26ca
BLAKE2b-256 de8cba3612b0209c8936a5b85925f408d9da1b207e5d172167677f45b03b3cc6

See more details on using hashes here.

File details

Details for the file cryolock-1.2.0-py2.py3-none-any.whl.

File metadata

  • Download URL: cryolock-1.2.0-py2.py3-none-any.whl
  • Upload date:
  • Size: 22.8 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.32.5

File hashes

Hashes for cryolock-1.2.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 f5a72029a94dd362c7bc0056bfbafb21d42f0b9ac22e7d0664cc01143869b55a
MD5 3fd041a26f91c72b860c30fb5a0763d8
BLAKE2b-256 41286373aff2aefd4ddce7f76fe3f563b15e1f261052befe09c7118b1e24469c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page