If an attempt to lock a file fails, the descriptor doesn't get closed. I'd
suggest to use bracket, something like

bracket (openFile ... >>= handleToFd) closeFd (setLock ...)

Perhaps also use openFd instead of openFile so that we don't need to
convert to a Handle and that we use just one type handling files here.



On Thu, Mar 6, 2014 at 2:37 PM, Klaus Aehlig <[email protected]> wrote:

> With jobs running in processes different from the lock management soon,
> we need to detect if a job holding locks dies, in order to release the
> resources.
>
> Signed-off-by: Klaus Aehlig <[email protected]>
> ---
>  Makefile.am                         |  1 +
>  src/Ganeti/WConfd/DeathDetection.hs | 56
> +++++++++++++++++++++++++++++++++++++
>  2 files changed, 57 insertions(+)
>  create mode 100644 src/Ganeti/WConfd/DeathDetection.hs
>
> diff --git a/Makefile.am b/Makefile.am
> index 07dc1c1..8ece27c 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -814,6 +814,7 @@ HS_LIB_SRCS = \
>         src/Ganeti/WConfd/ConfigState.hs \
>         src/Ganeti/WConfd/ConfigWriter.hs \
>         src/Ganeti/WConfd/Core.hs \
> +       src/Ganeti/WConfd/DeathDetection.hs \
>         src/Ganeti/WConfd/Language.hs \
>         src/Ganeti/WConfd/Monad.hs \
>         src/Ganeti/WConfd/Server.hs
> diff --git a/src/Ganeti/WConfd/DeathDetection.hs
> b/src/Ganeti/WConfd/DeathDetection.hs
> new file mode 100644
> index 0000000..54a7cdc
> --- /dev/null
> +++ b/src/Ganeti/WConfd/DeathDetection.hs
> @@ -0,0 +1,56 @@
> +{-| Utility function for detecting the death of a job holding resources
> +
> +To clean up resources owned by jobs that die for some reason, we need
> +to detect whether a job is still alive. As we have no control over PID
> +reuse, our approach is that each requester for a resource has to provide
> +a file where it owns an exclusive lock on. The kernel will make sure the
> +lock is removed if the process dies. We can probe for such a lock by
> +requesting a shared lock on the file.
> +
> +-}
> +
> +{-
> +
> +Copyright (C) 2014 Google Inc.
> +
> +This program is free software; you can redistribute it and/or modify
> +it under the terms of the GNU General Public License as published by
> +the Free Software Foundation; either version 2 of the License, or
> +(at your option) any later version.
> +
> +This program is distributed in the hope that it will be useful, but
> +WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +General Public License for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with this program; if not, write to the Free Software
> +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> +02110-1301, USA.
> +
> +-}
> +
> +module Ganeti.WConfd.DeathDetection
> +  ( isDead
> +  ) where
> +
> +import Control.Monad
> +import System.Directory
> +import System.IO
> +import System.Posix.IO
> +
> +import Ganeti.BasicTypes
> +
> +-- | Detect whether a the process identified by the given path
> +-- does not exist any more. This function never fails and only
> +-- returns True if it has positive knowledge that the process
> +-- does not exist any more (i.e., if it managed successfully
> +-- obtain a shared lock on the file).
> +isDead :: FilePath -> IO Bool
> +isDead fpath = fmap (isOk :: Result () -> Bool) . runResultT . liftIO $ do
> +  filepresent <- doesFileExist fpath
> +  when filepresent $ do
> +    handle <- openFile fpath ReadMode
> +    fd <- handleToFd handle
> +    setLock fd (ReadLock, AbsoluteSeek, 0, 0)
> +    closeFd fd
> --
> 1.9.0.279.gdc9e3eb
>
>

Reply via email to