{"id":8416,"library":"pid","title":"Pidfile Management (pid)","description":"The `pid` library (current version 3.0.4) provides robust pidfile management capabilities, including stale detection and file-locking. It can be used as a context manager or a decorator to ensure only one instance of a process is running, and to handle cleanup of the pidfile on termination. It's a stable library with a focus on reliable process control.","status":"active","version":"3.0.4","language":"en","source_language":"en","source_url":"https://github.com/trbs/pid/","tags":["pidfile","process management","locking","context manager","daemon","single instance"],"install":[{"cmd":"pip install pid","lang":"bash","label":"Install `pid`"}],"dependencies":[],"imports":[{"symbol":"PidFile","correct":"from pid import PidFile"},{"note":"Used as a decorator for functions to manage a pidfile automatically.","symbol":"pidfile","correct":"from pid.decorator import pidfile"}],"quickstart":{"code":"import os\nimport time\nfrom pid import PidFile, PidFileAlreadyLockedError, PidFileAlreadyRunningError\n\ndef my_daemon_process():\n    print(\"Attempting to start process...\")\n    try:\n        # By default, creates pidfile in /var/run, or /tmp on some systems.\n        # pidname defaults to script name.\n        with PidFile('my_app_daemon') as p:\n            print(f\"Process PID: {os.getpid()} has acquired pidfile {p.path}\")\n            # Simulate daemon work\n            for i in range(5):\n                print(f\"Working... {i+1}/5\")\n                time.sleep(1)\n            print(\"Process finished work and released pidfile.\")\n    except PidFileAlreadyLockedError:\n        print(\"Error: Another instance of the process is already running and holds the lock.\")\n    except PidFileAlreadyRunningError:\n        print(\"Error: Another instance of the process is already running (pidfile exists and PID is active).\")\n    except Exception as e:\n        print(f\"An unexpected error occurred: {e}\")\n\nif __name__ == '__main__':\n    my_daemon_process()","lang":"python","description":"This quickstart demonstrates using `PidFile` as a context manager to ensure a single instance of a process is running. It attempts to create a pidfile, performs some simulated work, and automatically cleans up the pidfile upon exiting the `with` block. It also shows how to catch common exceptions if another instance is detected."},"warnings":[{"fix":"Ensure your code relies on the process environment being determined at the point of lock acquisition/check, not instance creation, especially in forking processes. Re-test daemonized applications if upgrading from <2.0.0.","message":"In version 2.0.0, the behavior of PidFile when used with daemon context managers (like python-daemon) changed. Previously, the process environment (PID) was determined when the PidFile class was instanced, which could lead to incorrect PID determination if a process forked afterward. Now, the environment is determined at the time of acquiring/checking the lock.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Be aware that `pid` installs its own `SIGTERM` handler for cleanup. If your application has its own `SIGTERM` handler, ensure it correctly integrates or is compatible with `pid`'s cleanup mechanism, or that your custom handler explicitly calls functions registered with `atexit`.","message":"The `pid` library uses the `atexit` module for pidfile cleanup on termination. However, the default `SIGTERM` handler on some systems might not cleanly exit, preventing `atexit` registered functions from executing. `pid` overrides the default `SIGTERM` handler to ensure cleanup, but this might interact with other custom signal handlers.","severity":"gotcha","affected_versions":"All"},{"fix":"When handling exceptions, consider catching `PidFileAlreadyLockedError` first if you expect concurrent access to the pidfile. Catching `PidFileError` (the base exception) will capture both `PidFileAlreadyLockedError` and `PidFileAlreadyRunningError` if you want a more general catch-all.","message":"By default, `PidFile` attempts to acquire a file lock using `fcntl` before checking if a process is running. This means you will typically receive a `PidFileAlreadyLockedError` if another instance holds the lock, rather than `PidFileAlreadyRunningError` which indicates a stale pidfile or an active process with the specified PID.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"This is often not an error but an informative message. If you want to allow multiple instances, the `pid` library might not be suitable or requires custom handling. To stop the existing instance, terminate the process with the reported PID (e.g., `kill 12345`).","cause":"Another instance of your application is currently running and successfully acquired the file lock on the pidfile. This is the expected behavior for single-instance applications.","error":"pid.PidFileAlreadyLockedError: Pidfile 'my_app_daemon.pid' already locked by PID 12345"},{"fix":"This usually indicates a stale pidfile or a mismanaged process. Verify if the process with the reported PID is indeed your application. If it's a legitimate active process, handle it as `PidFileAlreadyLockedError`. If it's a stale pidfile, `pid` should ideally clean it up if configured, but manual intervention (deleting the `.pid` file) might be necessary if cleanup failed.","cause":"A pidfile exists from a previous run (e.g., due to an unclean shutdown), and the PID within that file (12345 in this example) is still active on the system.","error":"pid.PidFileAlreadyRunningError: Pidfile 'my_app_daemon.pid' already running (pid 12345)"},{"fix":"Specify a writable directory for the pidfile using the `piddir` argument, e.g., `PidFile(pidname='my_app_daemon', piddir='/tmp')`. Alternatively, ensure the application is run with sufficient privileges or that the target directory has appropriate permissions.","cause":"The user running the application does not have write permissions to the directory where the pidfile is attempted to be created (e.g., `/var/run`). By default, `pid` tries to use system-wide paths.","error":"PermissionError: [Errno 13] Permission denied: '/var/run/my_app_daemon.pid'"},{"fix":"Install the library using pip: `pip install pid`.","cause":"The 'pid' library has not been installed in your current Python environment.","error":"ModuleNotFoundError: No module named 'pid'"}]}