diff --git a/Config/Internal.hs b/Config/Internal.hs
--- a/Config/Internal.hs
+++ b/Config/Internal.hs
@@ -21,11 +21,10 @@
   , opt_log_file = "/var/log/mighty"
   , opt_log_file_size = 16777216
   , opt_log_backup_number = 10
-  , opt_log_buffer_size = 16384
-  , opt_log_flush_period = 10
   , opt_index_file = "index.html"
   , opt_connection_timeout = 30
   , opt_server_name = programName ++ "/" ++ programVersion
+  , opt_worker_processes = 1
 }
 
 data Option = Option {
@@ -38,11 +37,10 @@
   , opt_log_file :: !String
   , opt_log_file_size :: !Int
   , opt_log_backup_number :: !Int
-  , opt_log_buffer_size :: !Int
-  , opt_log_flush_period :: !Int
   , opt_index_file :: !String
   , opt_connection_timeout :: !Int
   , opt_server_name :: !String
+  , opt_worker_processes :: !Int
 } deriving (Eq,Show)
 
 ----------------------------------------------------------------
@@ -63,11 +61,10 @@
   , opt_log_file           = get "Log_File" opt_log_file
   , opt_log_file_size      = get "Log_File_Size" opt_log_file_size
   , opt_log_backup_number  = get "Log_Backup_Number" opt_log_backup_number
-  , opt_log_buffer_size    = get "Log_Buffer_Size" opt_log_buffer_size
-  , opt_log_flush_period   = get "Log_Flush_Period" opt_log_flush_period
   , opt_index_file         = get "Index_File" opt_index_file
   , opt_connection_timeout = get "Connection_Timeout" opt_connection_timeout
   , opt_server_name        = get "Server_Name" opt_server_name
+  , opt_worker_processes   = get "Worker_Processes" opt_worker_processes
   }
   where
     get k func = maybe (func def) fromConf $ lookup k conf
diff --git a/FileCache.hs b/FileCache.hs
--- a/FileCache.hs
+++ b/FileCache.hs
@@ -1,4 +1,4 @@
-module FileCache where
+module FileCache (fileCacheInit) where
 
 import Control.Concurrent
 import Control.Exception
@@ -48,8 +48,8 @@
     handler :: SomeException -> IO (Cache, Maybe FileInfo)
     handler _ = neg
 
-initialize :: IO (GetInfo)
-initialize = do
+fileCacheInit :: IO GetInfo
+fileCacheInit = do
     ref <- newIORef M.empty
     forkIO (remover ref)
     return $ fileInfo ref
@@ -57,5 +57,5 @@
 remover :: IORef Cache -> IO ()
 remover ref = do
     threadDelay 10000000
-    _ <- atomicModifyIORef ref (\_ -> (M.empty, undefined))
+    _ <- atomicModifyIORef ref (\_ -> (M.empty, ()))
     remover ref
diff --git a/Log.hs b/Log.hs
--- a/Log.hs
+++ b/Log.hs
@@ -1,141 +1,35 @@
 {-# LANGUAGE OverloadedStrings #-}
 
-module Log where
+module Log (
+    logInit
+  , logController
+  , logCheck
+  , module Log.Types
+  ) where
 
 import Control.Concurrent
 import Control.Monad
-import qualified Data.ByteString.Char8 as BS
-import Data.ByteString.Lazy (ByteString)
-import qualified Data.ByteString.Lazy.Char8 as BL
-import Data.Time
-import Network.HTTP.Types
-import Network.Wai
-import Network.Wai.Application.Classic
-import System.Directory
-import System.Exit
-import System.FilePath
-import System.IO
-import System.Locale
-import System.Posix
-
-data FileLogSpec = FileLogSpec {
-    log_file :: String
-  , log_file_size :: Integer
-  , log_backup_number :: Int
-  , log_buffer_size :: Int
-  , log_flush_period :: Int
-  }
-
-fileCheck :: FileLogSpec -> IO ()
-fileCheck spec = do
-    dirperm <- getPermissions dir
-    unless (writable dirperm) $ exit $ dir ++ " is not writable"
-    fileexist <- doesFileExist file
-    when fileexist $ do
-        fileperm <- getPermissions file
-        unless (writable fileperm) $ exit $ file ++ " is not writable"
-  where
-    file = log_file spec
-    dir = takeDirectory file
-    exit msg = hPutStrLn stderr msg >> exitFailure
-
-fileInit :: FileLogSpec -> IO (Chan ByteString)
-fileInit spec = do
-    hdl <- open spec
-    mvar <- newMVar hdl
-    chan <- newChan
-    forkIO $ fileFlusher mvar spec
-    forkIO $ fileSerializer chan mvar
-    let handler = fileFlushHandler mvar
-    installHandler sigTERM handler Nothing
-    installHandler sigKILL handler Nothing
-    return chan
-
-fileFlushHandler :: MVar Handle -> Handler
-fileFlushHandler mvar = Catch $ do
-    hdl <- takeMVar mvar
-    hFlush hdl
-    putMVar mvar hdl
-    exitImmediately ExitSuccess
-
-fileFlusher :: MVar Handle -> FileLogSpec -> IO ()
-fileFlusher mvar spec = forever $ do
-    threadDelay $ log_flush_period spec
-    hdl <- takeMVar mvar
-    hFlush hdl
-    size <- hFileSize hdl
-    if size > log_file_size spec
-       then do
-        hClose hdl
-        locate spec
-        newhdl <- open spec
-        putMVar mvar newhdl
-       else putMVar mvar hdl
-
-fileSerializer :: Chan ByteString -> MVar Handle -> IO ()
-fileSerializer chan mvar = forever $ do
-    xs <- readChan chan
-    hdl <- takeMVar mvar
-    BL.hPut hdl xs
-    putMVar mvar hdl
-
-open :: FileLogSpec -> IO Handle
-open spec = do
-    hdl <- openFile file AppendMode
-    setFileMode file 0o644
-    hSetEncoding hdl latin1
-    hSetBuffering hdl $ BlockBuffering (Just $ log_buffer_size spec)
-    return hdl
-  where
-    file = log_file spec
-
-locate :: FileLogSpec -> IO ()
-locate spec = mapM_ move srcdsts
-  where
-    path = log_file spec
-    n = log_backup_number spec
-    dsts' = reverse . ("":) . map (('.':). show) $ [0..n-1]
-    dsts = map (path++) dsts'
-    srcs = tail dsts
-    srcdsts = zip srcs dsts
-    move (src,dst) = do
-        exist <- doesFileExist src
-        when exist $ renameFile src dst
+import Log.Check
+import Log.File
+import Log.Stdout
+import Log.Types
 
 ----------------------------------------------------------------
 
-stdoutInit :: IO (Chan ByteString)
-stdoutInit = do
-    chan <- newChan
-    forkIO $ stdoutSerializer chan
-    return chan
+logInit :: LogType -> IO Logger
+logInit LogNone        = noLoggerInit
+logInit LogStdout      = stdoutLoggerInit
+logInit (LogFile spec) = fileLoggerInit spec
 
-stdoutSerializer :: Chan ByteString -> IO ()
-stdoutSerializer chan = forever $ readChan chan >>= BL.putStr
+noLoggerInit :: IO Logger
+noLoggerInit = return noLogger
+  where
+    noLogger _ _ _ = return ()
 
-----------------------------------------------------------------
+logController :: LogType -> LogController
+logController LogNone        = noLoggerController
+logController LogStdout      = noLoggerController
+logController (LogFile spec) = fileLoggerController spec
 
-mightyLogger :: Chan ByteString -> Request -> Status -> Maybe Integer -> IO ()
-mightyLogger chan req st msize = do
-    zt <- getZonedTime
-    addr <- getPeerAddr (remoteHost req)
-    writeChan chan $ BL.fromChunks (logmsg addr zt)
-  where
-    logmsg addr zt = [
-        BS.pack addr
-      , " - - ["
-      , BS.pack (formatTime defaultTimeLocale "%d/%b/%Y:%T %z" zt)
-      , "] \""
-      , requestMethod req
-      , " "
-      , rawPathInfo req
-      , "\" "
-      , BS.pack (show . statusCode $ st)
-      , " "
-      , BS.pack (maybe "-" show msize)
-      , " \"" -- size
-      , lookupRequestField' "referer" req
-      , "\" \""
-      , lookupRequestField' "user-agent" req
-      , "\"\n"
-      ]
+noLoggerController :: LogController
+noLoggerController _ = forever $ threadDelay 10000000
diff --git a/Log/Apache.hs b/Log/Apache.hs
new file mode 100644
--- /dev/null
+++ b/Log/Apache.hs
@@ -0,0 +1,34 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Log.Apache where
+
+import Data.ByteString (ByteString)
+import Data.ByteString.Char8 ()
+import Network.HTTP.Types
+import Network.Wai
+import Network.Wai.Application.Classic
+import Log.Types
+
+apacheFormat :: ByteString -> Request -> Status -> Maybe Integer -> [LogStr]
+apacheFormat tmstr req st msize = [
+    LS addr
+  , LB " - - ["
+  , LB tmstr
+  , LB "] \""
+  , LB $ requestMethod req
+  , LB " "
+  , LB $ rawPathInfo req
+  , LB " "
+  , LS $ show . httpVersion $ req
+  , LB "\" "
+  , LS . show . statusCode $ st
+  , LB " "
+  , LS $ maybe "-" show msize
+  , LB " \""
+  , LB $ lookupRequestField' "referer" req
+  , LB "\" \""
+  , LB $ lookupRequestField' "user-agent" req
+  , LB "\"\n"
+  ]
+  where
+    addr = showSockAddr (remoteHost req)
diff --git a/Log/Check.hs b/Log/Check.hs
new file mode 100644
--- /dev/null
+++ b/Log/Check.hs
@@ -0,0 +1,22 @@
+module Log.Check (logCheck) where
+
+import Control.Monad
+import Log.Types
+import System.Directory
+import System.FilePath
+
+logCheck :: LogType -> IO ()
+logCheck LogNone   = return ()
+logCheck LogStdout = return ()
+logCheck (LogFile spec) = do
+    dirExist <- doesDirectoryExist dir
+    unless dirExist $ fail $ dir ++ " does not exist or is not a directory."
+    dirPerm <- getPermissions dir
+    unless (writable dirPerm) $ fail $ dir ++ " is not writable."
+    exist <- doesFileExist file
+    when exist $ do
+        perm <- getPermissions file
+        unless (writable perm) $ fail $ file ++ " is not writable."
+  where
+    file = log_file spec
+    dir = takeDirectory file
diff --git a/Log/Date.hs b/Log/Date.hs
new file mode 100644
--- /dev/null
+++ b/Log/Date.hs
@@ -0,0 +1,32 @@
+module Log.Date (dateInit, getDate, DateRef) where
+
+import Control.Applicative
+import Control.Concurrent
+import Data.ByteString (ByteString)
+import qualified Data.ByteString.Char8 as BS
+import Data.IORef
+import Data.Time
+import System.Locale
+
+newtype DateRef = DateRef (IORef ByteString)
+
+getDate :: DateRef -> IO ByteString
+getDate (DateRef ref) = readIORef ref
+
+dateInit :: IO DateRef
+dateInit = do
+    ref <- formatDate >>= newIORef
+    let dateref = DateRef ref
+    forkIO $ date dateref
+    return dateref
+
+date :: DateRef -> IO ()
+date dateref@(DateRef ref) = do
+    tmstr <- formatDate
+    atomicModifyIORef ref (\_ -> (tmstr, ()))
+    threadDelay 1000000
+    date dateref
+
+formatDate :: IO ByteString
+formatDate =
+    BS.pack . formatTime defaultTimeLocale "%d/%b/%Y:%T %z" <$> getZonedTime
diff --git a/Log/File.hs b/Log/File.hs
new file mode 100644
--- /dev/null
+++ b/Log/File.hs
@@ -0,0 +1,96 @@
+{-# LANGUAGE DoAndIfThenElse #-}
+
+module Log.File where
+
+import Control.Applicative
+import Control.Concurrent
+import Control.Exception (handle, SomeException, catch)
+import Control.Monad
+import Data.IORef
+import Log.Apache
+import Log.Date
+import Log.Hput
+import Log.Rotate
+import Log.Types
+import Prelude hiding (catch)
+import System.IO
+import System.Posix
+
+----------------------------------------------------------------
+
+logBufSize :: Int
+logBufSize = 4096
+
+----------------------------------------------------------------
+
+newtype HandleRef = HandleRef (IORef Handle)
+
+getHandle :: HandleRef -> IO Handle
+getHandle (HandleRef ref) = readIORef ref
+
+----------------------------------------------------------------
+
+fileLoggerInit :: FileLogSpec -> IO Logger
+fileLoggerInit spec = do
+    hdl <- open spec
+    hdlref <- HandleRef <$> newIORef hdl
+    forkIO $ fileFlusher hdlref
+    dateref <- dateInit
+    installHandler sigUSR1 (Catch $ reopen spec hdlref) Nothing
+    return $ fileLogger dateref hdlref
+
+{-
+ For BlockBuffering, hPut flushes the buffer before writing
+ the target string. In other words, hPut does not split
+ the target string. So, to implment multiple line buffering,
+ just use BlockBuffering.
+-}
+open :: FileLogSpec -> IO Handle
+open spec = do
+    hdl <- openFile file AppendMode
+    hSetBuffering hdl (BlockBuffering (Just logBufSize))
+    return hdl
+  where
+    file = log_file spec
+
+reopen :: FileLogSpec -> HandleRef -> IO ()
+reopen spec (HandleRef ref) = do
+    hdl <- open spec
+    oldhdl <- atomicModifyIORef ref (\oh -> (hdl,oh))
+    hClose oldhdl
+
+----------------------------------------------------------------
+
+fileLogger :: DateRef -> HandleRef -> Logger
+fileLogger dateref hdlref req status msiz = do
+    date <- getDate dateref
+    hdl <- getHandle hdlref
+    hPutByteStrings hdl $ apacheFormat date req status msiz
+
+fileFlusher :: HandleRef -> IO ()
+fileFlusher hdlref = forever $ do
+    threadDelay 10000000
+    getHandle hdlref >>= hFlush
+
+----------------------------------------------------------------
+
+fileLoggerController :: FileLogSpec -> LogController
+fileLoggerController spec pids = forever $ do
+    isOver <- over
+    when isOver $ do
+        rotate spec
+        mapM_ sendSignal pids
+    threadDelay 10000000
+  where
+    file = log_file spec
+    over = handle handler $ do
+        siz <- fromIntegral . fileSize <$> getFileStatus file
+        if siz > log_file_size spec then
+            return True
+        else
+            return False
+    sendSignal pid = signalProcess sigUSR1 pid `catch` ignore
+    handler :: SomeException -> IO Bool
+    handler _ = return False
+    ignore :: SomeException -> IO ()
+    ignore _ = return ()
diff --git a/Log/Hput.hs b/Log/Hput.hs
new file mode 100644
--- /dev/null
+++ b/Log/Hput.hs
@@ -0,0 +1,63 @@
+{-# LANGUAGE DoAndIfThenElse, BangPatterns #-}
+{-# LANGUAGE NoImplicitPrelude, RecordWildCards #-}
+
+module Log.Hput (hPutByteStrings) where
+
+import qualified Data.ByteString as BS
+import Data.ByteString.Internal (ByteString(..), c2w)
+import Data.List
+import Foreign
+import GHC.Base
+import GHC.IO.Buffer
+import qualified GHC.IO.BufferedIO as Buffered
+import GHC.IO.Handle.Internals
+import GHC.IO.Handle.Text
+import GHC.IO.Handle.Types
+import GHC.IORef
+import GHC.Num
+import GHC.Real
+import Log.Types
+
+hPutByteStrings :: Handle -> [LogStr] -> IO ()
+hPutByteStrings handle bss =
+  wantWritableHandle "hPutByteStrings" handle $ \h_ -> bufsWrite h_ bss
+
+bufsWrite :: Handle__-> [LogStr] -> IO ()
+bufsWrite h_@Handle__{..} bss = do
+    old_buf@Buffer{
+        bufRaw = old_raw
+      , bufR = w
+      , bufSize = size
+      } <- readIORef haByteBuffer
+    if size - w > len then do
+        withRawBuffer old_raw $ \ptr ->
+            go (ptr `plusPtr` w)  bss
+        writeIORef haByteBuffer old_buf{ bufR = w + len }
+    else do
+        old_buf' <- Buffered.flushWriteBuffer haDevice old_buf
+        writeIORef haByteBuffer old_buf'
+        bufsWrite h_ bss
+  where
+    len = foldl' (\x y -> x + getLength y) 0 bss
+    getLength (LB s) = BS.length s
+    getLength (LS s) = length s
+    go :: Ptr Word8 -> [LogStr] -> IO ()
+    go _ [] = return ()
+    go dst (LB b:bs) = do
+      dst' <- copy dst b
+      go dst' bs
+    go dst (LS s:ss) = do
+      dst' <- copy' dst s
+      go dst' ss
+
+copy :: Ptr Word8 -> ByteString -> IO (Ptr Word8)
+copy dst (PS ptr off len) = withForeignPtr ptr $ \s -> do
+    let src = s `plusPtr` off
+    memcpy dst src (fromIntegral len)
+    return (dst `plusPtr` len)
+
+copy' :: Ptr Word8 -> String -> IO (Ptr Word8)
+copy' dst [] = return dst
+copy' dst (x:xs) = do
+    poke dst (c2w x)
+    copy' (dst `plusPtr` 1) xs
diff --git a/Log/Rotate.hs b/Log/Rotate.hs
new file mode 100644
--- /dev/null
+++ b/Log/Rotate.hs
@@ -0,0 +1,18 @@
+module Log.Rotate where
+
+import Control.Monad
+import System.Directory
+import Log.Types
+
+rotate :: FileLogSpec -> IO ()
+rotate spec = mapM_ move srcdsts
+  where
+    path = log_file spec
+    n = log_backup_number spec
+    dsts' = reverse . ("":) . map (('.':). show) $ [0..n-1]
+    dsts = map (path++) dsts'
+    srcs = tail dsts
+    srcdsts = zip srcs dsts
+    move (src,dst) = do
+        exist <- doesFileExist src
+        when exist $ renameFile src dst
diff --git a/Log/Stdout.hs b/Log/Stdout.hs
new file mode 100644
--- /dev/null
+++ b/Log/Stdout.hs
@@ -0,0 +1,19 @@
+module Log.Stdout (stdoutLoggerInit) where
+
+import Control.Applicative
+import qualified Data.ByteString as BS
+import Data.ByteString.Char8 (pack)
+import Log.Apache
+import Log.Date
+import Log.Types
+
+stdoutLoggerInit :: IO Logger
+stdoutLoggerInit = stdoutLogger <$> dateInit
+
+stdoutLogger :: DateRef -> Logger
+stdoutLogger dateref req status msiz = do
+    date <- getDate dateref
+    BS.putStr $ BS.concat $ map toBS $ apacheFormat date req status msiz
+  where
+    toBS (LS s) = pack s
+    toBS (LB s) = s
diff --git a/Log/Types.hs b/Log/Types.hs
new file mode 100644
--- /dev/null
+++ b/Log/Types.hs
@@ -0,0 +1,23 @@
+module Log.Types (
+    Logger
+  , FileLogSpec(..)
+  , LogType(..)
+  , LogController
+  , LogStr(..)
+  ) where
+
+import Data.ByteString
+import Network.Wai.Application.Classic (Logger)
+import System.Posix (ProcessID)
+
+data FileLogSpec = FileLogSpec {
+    log_file :: String
+  , log_file_size :: Integer
+  , log_backup_number :: Int
+  }
+
+data LogType = LogNone | LogStdout | LogFile FileLogSpec
+
+type LogController = [ProcessID] -> IO ()
+
+data LogStr = LS !String | LB !ByteString
diff --git a/Mighty.hs b/Mighty.hs
--- a/Mighty.hs
+++ b/Mighty.hs
@@ -1,12 +1,14 @@
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings, DoAndIfThenElse #-}
 
 module Main where
 
 import Config
-import Control.Exception (handle, SomeException)
+import Control.Concurrent
+import Control.Exception (catch, handle, SomeException)
 import Control.Monad
 import qualified Data.ByteString.Char8 as BS
 import FileCGIApp
+import FileCache
 import Log
 import Network
 import Network.Wai.Application.Classic
@@ -18,15 +20,15 @@
 import System.IO
 import System.Posix
 import Types
-import FileCache
 
 main :: IO ()
 main = do
     opt  <- fileName 0 >>= parseOption
     route <- fileName 1 >>= parseRoute
-    if opt_debug_mode opt
-       then server opt route
-       else daemonize $ server opt route
+    if opt_debug_mode opt then
+        server opt route
+    else
+        daemonize $ server opt route
   where
     fileName n = do
         args <- getArgs
@@ -35,53 +37,83 @@
             exitFailure
         return $ args !! n
 
+----------------------------------------------------------------
+
 server :: Option -> RouteDB -> IO ()
 server opt route = handle handler $ do
     s <- sOpen
-    installHandler sigCHLD Ignore Nothing
     unless debug writePidFile
     setGroupUser opt
-    lgr <- if opt_logging opt
-              then do
-               chan <- if debug then stdoutInit else fileInit logspec
-               return $ mightyLogger chan
-              else return (\_ _ _ -> return ())
-    fif <- initialize
-    runSettingsSocket setting s $ fileCgiApp (spec lgr fif) route
+    logCheck logtype
+    if workers == 1 then do
+        forkIO $ single opt route s logtype
+        myid <- getProcessID
+        logController logtype [myid]
+    else do
+        cids <- multi opt route s logtype
+        logController logtype cids
   where
     debug = opt_debug_mode opt
     port = opt_port opt
-    ignore = const $ return ()
     sOpen = listenOn (PortNumber . fromIntegral $ port)
-    spec lgr fif = AppSpec {
-        softwareName = BS.pack $ opt_server_name opt
-      , indexFile = BS.pack $ opt_index_file opt
-      , isHTML = \x -> ".html" `BS.isSuffixOf` x || ".htm" `BS.isSuffixOf` x
-      , logger = lgr
-      , getFileInfo = fif
-      }
+    pidfile = opt_pid_file opt
+    workers = opt_worker_processes opt
+    writePidFile = do
+        pid <- getProcessID
+        writeFile pidfile $ show pid ++ "\n"
+        setFileMode pidfile 0o644
+    handler :: SomeException -> IO ()
+    handler e
+      | debug = hPutStrLn stderr $ show e
+      | otherwise = writeFile "/tmp/mighty_error" (show e)
     logspec = FileLogSpec {
         log_file          = opt_log_file opt
       , log_file_size     = fromIntegral $ opt_log_file_size opt
       , log_backup_number = opt_log_backup_number opt
-      , log_buffer_size   = opt_log_buffer_size opt
-      , log_flush_period  = opt_log_flush_period opt * 1000000
       }
+    logtype
+      | not (opt_logging opt) = LogNone
+      | debug                 = LogStdout
+      | otherwise             = LogFile logspec
+
+----------------------------------------------------------------
+
+single :: Option -> RouteDB -> Socket -> LogType -> IO ()
+single opt route s logtype = do
+    lgr <- logInit logtype
+    getInfo <- fileCacheInit
+    runSettingsSocket setting s $ fileCgiApp (spec lgr getInfo) route
+  where
     setting = defaultSettings {
         settingsPort        = opt_port opt
       , settingsOnException = ignore
       , settingsTimeout     = opt_connection_timeout opt
       }
-    pidfile = opt_pid_file opt
-    writePidFile = do
-        pid <- getProcessID
-        writeFile pidfile $ show pid ++ "\n"
-        setFileMode pidfile 0o644
-    handler :: SomeException -> IO ()
-    handler e
-      | debug = hPutStrLn stderr $ show e
-      | otherwise = writeFile "/tmp/mighty_error" (show e)
+    spec lgr getInfo = AppSpec {
+        softwareName = BS.pack $ opt_server_name opt
+      , indexFile = BS.pack $ opt_index_file opt
+      , isHTML = \x -> ".html" `BS.isSuffixOf` x || ".htm" `BS.isSuffixOf` x
+      , logger = lgr
+      , getFileInfo = getInfo
+      }
 
+multi :: Option -> RouteDB -> Socket -> LogType -> IO [ProcessID]
+multi opt route s logtype = do
+    ignoreSigChild
+    cids <- replicateM workers $ forkProcess (single opt route s logtype)
+    sClose s
+    initHandler sigTERM $ terminateHandler cids
+    initHandler sigINT  $ terminateHandler cids
+    return cids
+  where
+    workers = opt_worker_processes opt
+    initHandler sig func = installHandler sig func Nothing
+    ignoreSigChild = initHandler sigCHLD Ignore
+    terminateHandler cids = Catch $ do
+        mapM_ terminateChild cids
+        exitImmediately ExitSuccess
+    terminateChild cid = signalProcess sigTERM cid `catch` ignore
+
 ----------------------------------------------------------------
 
 setGroupUser :: Option -> IO ()
@@ -109,3 +141,8 @@
         forkProcess p
         exitImmediately ExitSuccess
     detachTerminal = createSession
+
+----------------------------------------------------------------
+
+ignore :: SomeException -> IO ()
+ignore = const $ return ()
diff --git a/Types.hs b/Types.hs
--- a/Types.hs
+++ b/Types.hs
@@ -15,4 +15,4 @@
 programName = "Mighttpd"
 
 programVersion :: String
-programVersion = "2.2.2"
+programVersion = "2.3.0"
diff --git a/mighttpd2.cabal b/mighttpd2.cabal
--- a/mighttpd2.cabal
+++ b/mighttpd2.cabal
@@ -1,5 +1,5 @@
 Name:                   mighttpd2
-Version:                2.2.2
+Version:                2.3.0
 Author:                 Kazu Yamamoto <kazu@iij.ad.jp>
 Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp>
 License:                BSD3
@@ -14,34 +14,34 @@
 Data-Files:             sample.conf sample.route
 Executable mighty
   Main-Is:              Mighty.hs
-  if impl(ghc >= 7)
-    GHC-Options:        -Wall -fno-warn-unused-do-bind -threaded
-  else
-    if impl(ghc >= 6.12)
-      GHC-Options:        -Wall -fno-warn-unused-do-bind
-    else
-      GHC-Options:        -Wall
+  GHC-Options:          -Wall -fno-warn-unused-do-bind -threaded
   Build-Depends:        base >= 4.0 && < 5, parsec >= 3,
                         network,
-                        unix, bytestring, warp, old-locale, time,
+                        unix, bytestring, unix-bytestring,
+                        warp, old-locale, time,
                         wai-app-file-cgi, wai, transformers, http-types,
                         directory, filepath,
                         haskell98, http-date, hashmap
   Other-Modules:	Config
                         Config.Internal
                         FileCGIApp
+                        FileCache
                         Log
+                        Log.Apache
+                        Log.Check
+                        Log.Date
+                        Log.File
+                        Log.Hput
+                        Log.Rotate
+                        Log.Stdout
+                        Log.Types
                         Mighty
                         Parser
                         Route
                         Types
-                        FileCache
 Executable mkindex
   Main-Is:              mkindex.hs
-  if impl(ghc >= 6.12)
-    GHC-Options:        -Wall -fno-warn-unused-do-bind
-  else
-    GHC-Options:        -Wall
+  GHC-Options:          -Wall -fno-warn-unused-do-bind
   Build-Depends:        base >= 4 && < 5
 Source-Repository head
   Type:                 git
diff --git a/mkindex.hs b/mkindex.hs
--- a/mkindex.hs
+++ b/mkindex.hs
@@ -57,7 +57,7 @@
   | otherwise      = sizeFormat . fromIntegral . fileSize $ st
   where
     sizeFormat siz = unit siz " KMGT"
-    unit _ []  = undefined
+    unit _ []  = error "unit"
     unit s [u] = format s u
     unit s (u:us)
       | s >= 1024 = unit (s `div` 1024) us
diff --git a/sample.conf b/sample.conf
--- a/sample.conf
+++ b/sample.conf
@@ -4,12 +4,11 @@
 User: nobody
 Group: nobody
 Pid_File: /var/run/mighty.pid
-Logging: Yes
+Logging: Yes # Yes or No
 Log_File: /var/log/mighty # The directory must be writable by Users:
 Log_File_Size: 16777216 # bytes
-Log_Backup_Number: 10 # seconds
-Log_Buffer_Size: 16384 # bytes
-Log_Flush_Period: 10 # seconds
+Log_Backup_Number: 10
 Index_File: index.html
 Connection_Timeout: 30 # seconds
 # Server_Name: Mighttpd/2.x.y
+Worker_Processes: 1
