packages feed

hws-1.1.0.1: src/ErrorLogger.hs

-- -----------------------------------------------------------------------------
-- Copyright 2002, Simon Marlow.
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are
-- met:
-- 
--  * Redistributions of source code must retain the above copyright notice,
--    this list of conditions and the following disclaimer.
-- 
--  * Redistributions in binary form must reproduce the above copyright
--    notice, this list of conditions and the following disclaimer in the
--    documentation and/or other materials provided with the distribution.
-- 
--  * Neither the name of the copyright holder(s) nor the names of
--    contributors may be used to endorse or promote products derived from
--    this software without specific prior written permission.
-- 
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- -----------------------------------------------------------------------------

module ErrorLogger (
	startErrorLogger, 
	stopErrorLogger, 
	logError, 
	catchAndLogError,
	showIOError
  ) where

import Config
import Util

import Time
import IO
import Foreign
import Control.Concurrent
import Control.Exception

import GHC.IO.Exception (IOException(..))

-----------------------------------------------------------------------------
-- Error Logging

logError :: String -> IO ()
logError err
  = writeChan error_log_chan err
    
error_log_chan :: Chan String
error_log_chan = unsafePerformIO (newChan)

error_log_pid :: MVar ThreadId
error_log_pid = unsafePerformIO (newEmptyMVar)

startErrorLogger :: Config -> IO ()
startErrorLogger conf = do
  logError ("error logger started (level " ++ show (logLevel conf) ++  
	    ") on '" ++ errorLogFile conf ++ "'")
  t <- forkIO (Control.Exception.catch (run_error_logger conf) (error_handler conf))
  putMVar error_log_pid t

stopErrorLogger :: IO ()
stopErrorLogger = do
   t <- takeMVar error_log_pid
   throwTo t (ErrorCall "**stop**")

error_handler conf (ErrorCall "**stop**") =
   logError ("error logger stopped")
error_handler conf exception = do
   logError ("error logger died: " ++ show exception)
   Control.Exception.catch (run_error_logger conf) (error_handler conf)

run_error_logger conf = do
   Control.Exception.bracket 
      (openFile (errorLogFile conf) AppendMode) 
      (\hdl -> hClose hdl)
      (\hdl -> doErrLogRequests hdl)

doErrLogRequests hdl = do
  str <- readChan error_log_chan
  clock_time <- getClockTime
  let time_str = formatTimeSensibly (toUTCTime clock_time)
  hPutStr hdl time_str
  hPutStrLn hdl ("  " ++ str)
  hFlush hdl
  doErrLogRequests hdl

catchAndLogError :: Exception e => String -> IO a -> (e -> IO a) -> IO a
catchAndLogError str io handler 
  = Control.Exception.catch io (\e -> logError (str ++ show e) >> handler e)

showIOError :: IOException -> String
showIOError (IOError _hdl iot loc s _errno filepath)
  = ( showString loc
    . showString ": "
    . shows iot
    . showString " ("
    . showString s
    . showChar ')'
  ) ""