From 1a865afe5bdd78bfd2023e6b07a5820abf2949ab Mon Sep 17 00:00:00 2001 From: Iustin Pop <iustin@google.com> Date: Tue, 6 Nov 2012 15:23:34 +0100 Subject: [PATCH] Properly log errors when setting up daemon FDs While writing the pipe-based reporting and trying various ways to break the startup, I fought for a while trying to understand why error reporting was _different_ when running the daemon as a user (with no rights). It turns out that setupDaemonFDs wants to open the log file in append mode way before, so we are not protected by the 'prepare' phase. This patch explicitly runs the 'setupDaemonFDs' function under the same handler as the prepare phase, with the only change that here we instruct handlePrepErr to not log the message via log*, since logging is not yet set up. Signed-off-by: Iustin Pop <iustin@google.com> Reviewed-by: Michael Hanselmann <hansmi@google.com> --- htools/Ganeti/Daemon.hs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/htools/Ganeti/Daemon.hs b/htools/Ganeti/Daemon.hs index 8ad738796..73bdb1669 100644 --- a/htools/Ganeti/Daemon.hs +++ b/htools/Ganeti/Daemon.hs @@ -309,12 +309,14 @@ daemonize logfile action = do _ <- forkProcess $ do -- in the child closeFd rpipe + let wpipe' = Just wpipe setupDaemonEnv "/" (unionFileModes groupModes otherModes) - setupDaemonFDs $ Just logfile + setupDaemonFDs (Just logfile) `Control.Exception.catch` + handlePrepErr False wpipe' _ <- installHandler lostConnection (Catch (handleSigHup logfile)) Nothing -- second fork, launches the actual child code; standard -- double-fork technique - _ <- forkProcess (action (Just wpipe)) + _ <- forkProcess (action wpipe') exitImmediately ExitSuccess closeFd wpipe hndl <- fdToHandle rpipe @@ -397,21 +399,21 @@ innerMain :: GanetiDaemon -- ^ The daemon we're running -> IO () innerMain daemon opts syslog check_result prep_fn exec_fn fd = do prep_result <- fullPrep daemon opts syslog check_result prep_fn - `Control.Exception.catch` handlePrepErr fd + `Control.Exception.catch` handlePrepErr True fd -- no error reported, we should now close the fd maybeCloseFd fd exec_fn opts check_result prep_result -- | Daemon prepare error handling function. -handlePrepErr :: Maybe Fd -> IOError -> IO a -handlePrepErr fd err = do +handlePrepErr :: Bool -> Maybe Fd -> IOError -> IO a +handlePrepErr logging_setup fd err = do let msg = show err case fd of -- explicitly writing to the fd directly, since when forking it's -- better (safer) than trying to convert this into a full handle Just fd' -> fdWrite fd' msg >> return () Nothing -> hPutStrLn stderr (daemonStartupErr msg) - logError msg + when logging_setup $ logError msg exitWith $ ExitFailure 1 -- | Close a file descriptor. -- GitLab