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 > >
