From e14b84e9ff1c5e207d1c6f1f10044ab3583d9377 Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Tue, 6 Nov 2012 14:53:45 +0100
Subject: [PATCH] Switch writing of PID file to new reporting style

Currently, the writing of the PID file uses a "standard" error
reporting: catch exception, transform it into a 'Result' type, leave
handling of that to the caller. However, for daemon startup, we
actually want exceptions to be propagated up until the handler which
will write the details to the pipe.

This patch removes the writePidFile wrapper (and stops exporting it),
and changes the code to simply annotate better the I/O error.

Signed-off-by: Iustin Pop <iustin@google.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>
---
 htools/Ganeti/Daemon.hs | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/htools/Ganeti/Daemon.hs b/htools/Ganeti/Daemon.hs
index 51f08059a..f87e49c5c 100644
--- a/htools/Ganeti/Daemon.hs
+++ b/htools/Ganeti/Daemon.hs
@@ -41,7 +41,7 @@ module Ganeti.Daemon
   , parseArgs
   , parseAddress
   , cleanupSocket
-  , writePidFile
+  , describeError
   , genericMain
   ) where
 
@@ -55,7 +55,7 @@ import System.Console.GetOpt
 import System.Exit
 import System.Environment
 import System.IO
-import System.IO.Error (isDoesNotExistError)
+import System.IO.Error (isDoesNotExistError, modifyIOError, annotateIOError)
 import System.Posix.Directory
 import System.Posix.Files
 import System.Posix.IO
@@ -206,26 +206,14 @@ pidFileMode :: FileMode
 pidFileMode = unionFileModes ownerReadMode ownerWriteMode
 
 -- | Writes a PID file and locks it.
-_writePidFile :: FilePath -> IO Fd
-_writePidFile path = do
+writePidFile :: FilePath -> IO Fd
+writePidFile path = do
   fd <- createFile path pidFileMode
   setLock fd (WriteLock, AbsoluteSeek, 0, 0)
   my_pid <- getProcessID
   _ <- fdWrite fd (show my_pid ++ "\n")
   return fd
 
--- | Helper to format an IOError.
-formatIOError :: String -> IOError -> String
-formatIOError msg err = msg ++ ": " ++  show err
-
--- | Wrapper over '_writePidFile' that transforms IO exceptions into a
--- 'Bad' value.
-writePidFile :: FilePath -> IO (Result Fd)
-writePidFile path =
-  Control.Exception.catch
-    (fmap Ok $ _writePidFile path)
-    (return . Bad . formatIOError "Failure during writing of the pid file")
-
 -- | Helper function to ensure a socket doesn't exist. Should only be
 -- called once we have locked the pid file successfully.
 cleanupSocket :: FilePath -> IO ()
@@ -298,7 +286,13 @@ parseAddress opts defport = do
                     (resolveAddr port saddr)
                     (ioErrorToResult $ "Invalid address " ++ saddr)
 
--- | Run an I/O action as a daemon.
+-- | Run an I\/O action that might throw an I\/O error, under a
+-- handler that will simply annotate and re-throw the exception.
+describeError :: String -> Maybe Handle -> Maybe FilePath -> IO a -> IO a
+describeError descr hndl fpath =
+  modifyIOError (\e -> annotateIOError e descr hndl fpath)
+
+-- | Run an I\/O action as a daemon.
 --
 -- WARNING: this only works in single-threaded mode (either using the
 -- single-threaded runtime, or using the multi-threaded one but with
@@ -376,9 +370,10 @@ fullPrep daemon opts syslog check_result prep_fn = do
   let logfile = if optDaemonize opts
                   then Nothing
                   else Just $ daemonLogFile daemon
+      pidfile = daemonPidFile daemon
   setupLogging logfile (daemonName daemon) (optDebug opts) True False syslog
-  pid_fd <- writePidFile (daemonPidFile daemon)
-  _ <- exitIfBad "Cannot write PID file; already locked? Error" pid_fd
+  _ <- describeError "writing PID file; already locked?"
+         Nothing (Just pidfile) $ writePidFile pidfile
   logNotice "starting"
   prep_fn opts check_result
 
-- 
GitLab