{"id":15063887,"url":"https://github.com/trskop/lock-file","last_synced_at":"2025-04-10T11:26:27.215Z","repository":{"id":9498159,"uuid":"11390471","full_name":"trskop/lock-file","owner":"trskop","description":"Provide exclusive access to a resource using lock file.","archived":false,"fork":false,"pushed_at":"2018-08-11T10:31:39.000Z","size":57,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-24T10:12:16.263Z","etag":null,"topics":["haskell","linux","lock-file","posix"],"latest_commit_sha":null,"homepage":null,"language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trskop.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-07-13T16:10:48.000Z","updated_at":"2023-06-27T14:47:41.000Z","dependencies_parsed_at":"2022-09-06T05:31:46.083Z","dependency_job_id":null,"html_url":"https://github.com/trskop/lock-file","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trskop%2Flock-file","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trskop%2Flock-file/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trskop%2Flock-file/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trskop%2Flock-file/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trskop","download_url":"https://codeload.github.com/trskop/lock-file/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247805290,"owners_count":20999147,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["haskell","linux","lock-file","posix"],"created_at":"2024-09-25T00:08:28.864Z","updated_at":"2025-04-10T11:26:27.196Z","avatar_url":"https://github.com/trskop.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"Lock File\n=========\n\n[![Haskell Programming Language](https://img.shields.io/badge/language-Haskell-blue.svg)][Haskell.org]\n[![BSD3 License](http://img.shields.io/badge/license-BSD3-brightgreen.svg)][tl;dr Legal: BSD3]\n\n[![Hackage](http://img.shields.io/hackage/v/lock-file.svg)][Hackage: lock-file]\n[![Build](https://travis-ci.org/trskop/lock-file.svg)](https://travis-ci.org/trskop/lock-file)\n\n\nDescription\n-----------\n\nProvide exclusive access to a resource using lock file, which are files whose\npurpose is to signal by their presence that some resource is locked.\n\n\nUsage Example\n-------------\n\nFollowing example acquires lock file and then waits `1000000` micro seconds\nbefore releasing it. Note also that it is possible to specify retry strategy.\nHere we set it to `No` and therefore this code won't retry to acquire lock file\nafter first failure.\n\n```Haskell\n{-# LANGUAGE TypeApplications #-}\n-- |\n-- Module:       Main\n-- Description:  Simple example that acquires lock for a short period of time.\n-- Copyright:    (c) 2013, 2014 Peter Trsko\n-- License:      BSD3\n--\n-- Maintainer:   peter.trsko@gmail.com\n-- Stability:    experimental\n-- Portability:  portable\nmodule Main (main)\n  where\n\nimport Control.Concurrent (threadDelay)\n    -- From base package, but GHC specific.\nimport qualified Control.Exception as Exception (handle)\n\nimport Data.Default.Class (Default(def))\n    -- From data-default-class package, alternatively it's possible to use\n    -- data-default package version 0.5.2 and above.\n    -- http://hackage.haskell.org/package/data-default-class\n    -- http://hackage.haskell.org/package/data-default\nimport System.IO.LockFile\n    ( LockingException\n    , LockingParameters(retryToAcquireLock)\n    , RetryStrategy(No)\n    , withLockFile\n    )\n\n\nmain :: IO ()\nmain = handleException\n    . withLockFile lockParams lockFile $ threadDelay 1000000\n  where\n    lockParams = def\n        { retryToAcquireLock = No\n        }\n\n    lockFile = \"/var/run/lock/my-example-lock\"\n\n    handleException = Exception.handle\n        $ putStrLn . (\"Locking failed with: \" ++) . show @LockingException\n```\n\nThis command line example shows that trying to execute two instances of\n`example` at the same time will result in failure of the second one.\n\n```\nstack ghc example/example.hs\n[1 of 1] Compiling Main             ( example/example.hs, example/example.o )\nLinking example/example ...\n$ ./example/example \u0026 ./example/example\n[1] 7893\nLocking failed with: Unable to acquire lock file: \"/var/run/lock/my-example-lock\"\n$ [1]+  Done                    ./example/example\n```\n\nPID File Example\n----------------\n\nLock file, as implemented by this library, is created containing PID of the\nprocess that created it. PID file, on UNIX-like system, is a special case of\nlock file. It prevents the same daemon to be started up multiple times.\n\nThanks to the above fact we can now create function with following type\nsignature:\n\n```Haskell\nwithPidFile :: IO () -\u003e IO ()\n```\n\nIts purpose is to wrap application `main` and acquire PID file prior to passing\ncontrol to the application code, or fail if PID file is already acquired.\n\n```Haskell\n{-# LANGUAGE LambdaCase #-}\n{-# LANGUAGE NoImplicitPrelude #-}\nmodule Main\n  where\n\nimport Control.Applicative (pure)\nimport Control.Concurrent (threadDelay)\nimport Control.Exception (catch)\nimport Control.Monad ((\u003e=\u003e), (\u003e\u003e=))\nimport Data.Function ((.), ($), const)\nimport Data.Functor ((\u003c$\u003e))\nimport Data.Monoid ((\u003c\u003e))\nimport System.Environment (getEnv, getProgName)\nimport System.Exit (exitFailure)\nimport System.IO (IO, FilePath, hPutStrLn, putStrLn, stderr)\nimport Text.Show (show, showString)\n\nimport System.Posix.User (getEffectiveUserID)\n\nimport Data.Default.Class (def)\nimport System.IO.LockFile\n    ( LockingException(CaughtIOException, UnableToAcquireLockFile)\n    , LockingParameters(retryToAcquireLock)\n    , RetryStrategy(No)\n    , withLockFile\n    )\n\n\nwithPidFile :: IO () -\u003e IO ()\nwithPidFile m = do\n    pidFilePath \u003c- mkPidFilePath\n    withLockFile def{retryToAcquireLock = No} pidFilePath m\n        `catch` (printLockingException pidFilePath \u003e=\u003e const exitFailure)\n  where\n    mkPidFilePath :: IO FilePath\n    mkPidFilePath = do\n        fileName \u003c- (\u003c\u003e \".pid\") \u003c$\u003e getProgName\n        getEffectiveUserID \u003e\u003e= \\case\n            0 -\u003e pure $ \"/var/run/\" \u003c\u003e fileName\n            _ -\u003e (\u003c\u003e ('/' : '.' : fileName)) \u003c$\u003e getEnv \"HOME\"\n                -- This may throw exception if $HOME environment varialbe is\n                -- not set.\n\n    printLockingException :: FilePath -\u003e LockingException -\u003e IO ()\n    printLockingException filePath = hPutStrLn stderr . mkMsg . \\case\n        UnableToAcquireLockFile _ -\u003e \"File already exists.\"\n        CaughtIOException       e -\u003e show e\n      where\n        mkMsg =\n            showString filePath . showString \": Unable to create PID file: \"\n\nmain :: IO ()\nmain = withPidFile $ do\n    putStrLn \"Hello World!\"\n    threadDelay 1000000\n```\n\n\nBuilding options\n----------------\n\n* `pedantic` (disabled by default)\n\n    Pass additional warning flags to GHC.\n\n* `examples` (disabled by default)\n\n    Build example(s).\n\n\n\n[Hackage: lock-file]: https://hackage.haskell.org/package/lock-file \"Hackage: lock-file\"\n[Haskell.org]: http://www.haskell.org \"The Haskell Programming Language\"\n[tl;dr Legal: BSD3]: https://tldrlegal.com/license/bsd-3-clause-license-%28revised%29 \"BSD 3-Clause License (Revised)\"\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrskop%2Flock-file","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrskop%2Flock-file","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrskop%2Flock-file/lists"}