diff --git a/Network/FastCGI.hsc b/Network/FastCGI.hsc
--- a/Network/FastCGI.hsc
+++ b/Network/FastCGI.hsc
@@ -1,72 +1,79 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Network.FastCGI
--- Copyright   :  (c) Bjorn Bringert 2004-2005
+-- Copyright   :  (c) Bjorn Bringert 2004-2005, (c) Lemmih 2006
 -- License     :  BSD-style (see the file libraries/network/LICENSE)
 -- 
--- Maintainer  :  bjorn@bringert.net
+-- Maintainer  :  lemmih@gmail.com
 -- Stability   :  experimental
 -- Portability :  non-portable (uses FFI)
 --
 -- Interface for FastCGI <http://fastcgi.com/>, using the fcgiapp API.
 --
 -----------------------------------------------------------------------------
-module Network.FastCGI ({-runFastCGIConcurrent,-}
-                        runFastCGIorCGI, runOneFastCGIorCGI, 
-                        runFastCGI, runOneFastCGI,
-                        module Network.CGI) where
+module Network.FastCGI
+    ( 
+    -- * Single-threaded interface
+      runFastCGIorCGI
+    , runOneFastCGIorCGI
+    , runFastCGI
+    , runOneFastCGI
+    -- * Concurrent interface
+    , runFastCGIConcurrent
+    , runFastCGIConcurrent'
+    -- * Re-export
+    , module Network.CGI
+    ) where
 
-import Control.Concurrent (forkOS)
-import Control.Exception as Exception (catch, finally, throwIO)
-import Control.Monad (when, liftM)
+import Control.Concurrent ( forkOS )
+import Control.Concurrent.MVar
+import Control.Concurrent.QSem
+import Control.Exception as Exception (catch, finally)
+import Control.Monad    ( liftM )
 import Data.Word (Word8)
-import Foreign          ( Ptr, castPtr, nullPtr, plusPtr, peekArray0 
-                        , alloca
-		        , mallocBytes, free, throwIfNeg_, allocaBytes
-                        , mallocArray, reallocArray, withForeignPtr)
-import Foreign.C        ( CInt, CString, CStringLen, CChar, withCStringLen
-                        , peekCString, castCCharToChar )
+import Foreign          ( Ptr, castPtr, nullPtr, peekArray0 
+                        , alloca, mallocBytes, free, throwIfNeg_)
+import Foreign.C        ( CInt, CString, CStringLen
+                        , peekCString )
 import Foreign.Storable ( Storable (..) )
-import System.IO.Unsafe (unsafeInterleaveIO)
+import System.IO.Unsafe (unsafeInterleaveIO,unsafePerformIO)
 
 import Network.CGI
 import Network.CGI.Monad (runCGIT)
 import Network.CGI.Protocol (runCGIEnvFPS)
 
 import qualified Data.ByteString as BS
-import qualified Data.ByteString.Base as BSB
-import qualified Data.ByteString.Base as Lazy (LazyByteString(LPS))
 import qualified Data.ByteString.Lazy.Char8 as Lazy
+#if __GLASGOW_HASKELL__ >= 608
+import qualified Data.ByteString.Internal as BSB
+import qualified Data.ByteString.Unsafe   as BSB
+#else
+import qualified Data.ByteString.Base as BSB
+#endif
 
 -- For debugging
-import Control.Concurrent (myThreadId)
-import Prelude hiding (log)
-import System.Mem (performGC)
-import System.IO (hPutStrLn, stderr)
+import Control.Concurrent ( myThreadId )
+import Prelude hiding     ( log, catch )
+import System.IO          ( hPutStrLn, stderr )
 
 #include <fcgiapp.h>
 
-data FCGX_Stream = FCGX_Stream
+data FCGX_Stream
 type StreamPtr = Ptr FCGX_Stream
 type Environ = Ptr CString
 
-foreign import ccall threadsafe "fcgiapp.h FCGX_IsCGI" fcgx_isCGI
+foreign import ccall unsafe "fcgiapp.h FCGX_IsCGI" fcgx_isCGI
     :: IO CInt
 
-foreign import ccall threadsafe "fcgiapp.h FCGX_GetStr" fcgx_getStr
+foreign import ccall unsafe "fcgiapp.h FCGX_GetStr" fcgx_getStr
     :: CString -> CInt -> StreamPtr -> IO CInt
 
-foreign import ccall threadsafe "fcgiapp.h FCGX_PutStr" fcgx_putStr
+foreign import ccall unsafe "fcgiapp.h FCGX_PutStr" fcgx_putStr
     :: CString -> CInt -> StreamPtr -> IO CInt
 
---
--- This code uses the not MT safe functions of the fcgiapp API,
--- to avoid getting intermittent SIGPIPEs. Dunno why that happens.
---
-
-foreign import ccall "fcgiapp.h FCGX_Accept" fcgx_accept
+foreign import ccall threadsafe "fcgiapp.h FCGX_Accept" fcgx_accept
     :: Ptr StreamPtr -> Ptr StreamPtr -> Ptr StreamPtr -> Ptr Environ -> IO CInt
-foreign import ccall "fcgiapp.h FCGX_Finish" fcgx_finish
+foreign import ccall unsafe "fcgiapp.h FCGX_Finish" fcgx_finish
     :: IO ()
 
 -- | Handle a single CGI request, or FastCGI requests in an infinite loop.
@@ -76,7 +83,7 @@
 --   treats it as.
 runFastCGIorCGI :: CGI CGIResult -> IO ()
 runFastCGIorCGI f = do fcgi <- runOneFastCGIorCGI f
-                       if fcgi then performGC >> runFastCGIorCGI f
+                       if fcgi then runFastCGIorCGI f
                                else return ()
 
 -- | Handle a single FastCGI or CGI request. This lets you use the same program
@@ -92,7 +99,7 @@
 
 -- | Handle FastCGI requests in an infinite loop.
 runFastCGI :: CGI CGIResult -> IO ()
-runFastCGI f = runOneFastCGI f >> performGC >> runFastCGI f
+runFastCGI f = runOneFastCGI f >> runFastCGI f
 
 -- | Handle a single FastCGI request.
 runOneFastCGI :: CGI CGIResult -> IO ()
@@ -125,7 +132,7 @@
               -> StreamPtr
               -> Environ
               -> IO ()
-handleRequest f ins outs errs env =
+handleRequest f ins outs _errs env =
     do
     vars <- environToTable env
     input <- sRead ins
@@ -134,129 +141,87 @@
 
 
 
---
--- The following code uses the MT safe fcgiapp API,
--- but causes mod_fastcgi to get SIGPIPE once in a while.
---
-
-{-
-
-data FCGX_Request = FCGX_Request
+data FCGX_Request
 
-foreign import ccall threadsafe "fcgiapp.h FCGX_Init" fcgx_init
+foreign import ccall unsafe "fcgiapp.h FCGX_Init" fcgx_init
     :: IO CInt
 
-foreign import ccall threadsafe "fcgiapp.h FCGX_InitRequest" fcgx_initrequest
+foreign import ccall unsafe "fcgiapp.h FCGX_InitRequest" fcgx_initrequest
     :: Ptr FCGX_Request -> CInt -> CInt -> IO CInt
 
 foreign import ccall threadsafe "fcgiapp.h FCGX_Accept_r" fcgx_accept_r
     :: Ptr FCGX_Request -> IO CInt
 
-foreign import ccall threadsafe "fcgiapp.h FCGX_Finish_r" fcgx_finish_r
+foreign import ccall unsafe "fcgiapp.h FCGX_Finish_r" fcgx_finish_r
     :: Ptr FCGX_Request -> IO ()
 
--- | Like 'Network.NewCGI.runCGI', but uses the FastCGI interface.
-runFastCGI :: CGI CGIResult -> IO ()
-runFastCGI = runFastCGI' id
-
--- | Like 'Network.NewCGI.runCGI', but uses the FastCGI interface
+-- | Like 'Network.CGI.runCGI', but uses the FastCGI interface
 --   and forks off a new thread (using 'forkOS') for every request.
-runFastCGIConcurrent :: CGI CGIResult -> IO ()
-runFastCGIConcurrent = runFastCGI' fork
-    where fork m = do
-		   t <- forkOS m
-		   log $ "Created child: " ++ show t
+runFastCGIConcurrent :: Int -- ^ Max number of concurrent threads.
+                     -> CGI CGIResult -> IO ()
+runFastCGIConcurrent = runFastCGIConcurrent' forkOS
 
-runFastCGI' :: (IO () -> IO a) -> CGI CGIResult -> IO ()
-runFastCGI' fork f = do
-		     log "Calling FCGX_Init"
-		     testReturn "FCGX_Init" $ fcgx_init
-		     loop
-    where 
-    loop = do
-	   reqp <- acceptRequest
-	   log "Forking"
-	   fork (oneRequest f reqp `finally` finishRequest reqp)
-	   loop
+runFastCGIConcurrent' :: (IO () -> IO a) -- ^ How to fork a request.
+                      -> Int             -- ^ Max number of concurrent threads.
+                      -> CGI CGIResult -> IO ()
+runFastCGIConcurrent' fork m f
+    = do qsem <- newQSem m
+	 testReturn "FCGX_Init" $ fcgx_init
+         let loop = do waitQSem qsem
+                       reqp <- acceptRequest
+	               fork (oneRequestMT f reqp `finally` (finishRequest reqp >> signalQSem qsem))
+	               loop
+	 loop `catch` \e -> log (show e)
 
-oneRequest :: CGI CGIResult -> Ptr FCGX_Request -> IO ()
-oneRequest f r = do
+oneRequestMT :: CGI CGIResult -> Ptr FCGX_Request -> IO ()
+oneRequestMT f r = do
 		 env <- peekEnvp r
 		 vars <- environToTable env
 		 ins <- peekIn r
-		 input <- sStrictRead ins
-		 log "Running CGI action"
-		 output <- runCGIEnv vars input f
+		 input <- sRead ins
+		 output <- runCGIEnvFPS vars input (runCGIT f)
 		 outs <- peekOut r
-		 log "Returning output"
 		 sPutStr outs output
-
 --
 -- * FCGX_Reqest struct
 --
 
 acceptRequest :: IO (Ptr FCGX_Request)
 acceptRequest = do
-		log "Allocating FCGX_Request"
  		reqp <- mallocBytes (#size FCGX_Request)
-		initAndAccept reqp `onError` free reqp
+		initAndAccept reqp
 		return reqp
     where initAndAccept reqp = 
 	      do 
-	      log "Calling FCGX_InitRequest"
 	      testReturn "FCGX_InitRequest" $ fcgx_initrequest reqp 0 0
-	      log "Calling FCGX_Accept_r"
 	      testReturn "FCGX_Accept_r" $ fcgx_accept_r reqp
 
 finishRequest :: Ptr FCGX_Request -> IO ()
 finishRequest reqp = do
-		     log "Calling FCGX_Finish_r"
 		     fcgx_finish_r reqp
-		     log "Freeing FCGX_Request"
 		     free reqp
 
-peekIn, peekOut, peekErr :: Ptr FCGX_Request -> IO (Ptr FCGX_Stream)
+peekIn, peekOut, _peekErr :: Ptr FCGX_Request -> IO (Ptr FCGX_Stream)
 peekIn  = (#peek FCGX_Request, in)
 peekOut = (#peek FCGX_Request, out)
-peekErr = (#peek FCGX_Request, err)
+_peekErr = (#peek FCGX_Request, err)
 
 peekEnvp :: Ptr FCGX_Request -> IO Environ
 peekEnvp = (#peek FCGX_Request, envp)
 
--}
 
 --
 -- * Stream IO
 --
 
 sPutStr :: StreamPtr -> Lazy.ByteString -> IO ()
-sPutStr h (Lazy.LPS strs) = 
-    mapM_ (flip BSB.unsafeUseAsCStringLen (fcgxPutCStringLen h)) strs
+sPutStr h str = 
+    mapM_ (flip BSB.unsafeUseAsCStringLen (fcgxPutCStringLen h)) (Lazy.toChunks str)
 
 fcgxPutCStringLen :: StreamPtr -> CStringLen -> IO ()
 fcgxPutCStringLen h (cs,len) = 
     testReturn "FCGX_PutStr" $ fcgx_putStr cs (fromIntegral len) h
 
-{-
--- Based on Data.FastPackedString.hGetContents
-sRead :: StreamPtr -> IO BS.ByteString
-sRead h = do 
-    let start_size = 1024
-    p <- mallocArray start_size
-    i <- fcgx_getStr p start_size h
-    if i < start_size
-        then liftM BS.packMallocCString $ reallocArray p i
-        else f p start_size
-    where 
-        f p s = do 
-        let s' = 2 * s
-        p' <- reallocArray p s'
-        i  <- fcgx_getStr (p' `plusPtr` s) s h
-        if i < s 
-            then liftM BS.packMallocCString $ reallocArray p' (s + i)
-            else f p' s'
--}
-
 sRead :: StreamPtr -> IO Lazy.ByteString
 sRead h = buildByteString (fcgxGetBuf h) 4096
 
@@ -271,7 +236,7 @@
 -- | Data.ByteString.Lazy.hGetContentsN generalized to arbitrary 
 --   reading functions.
 buildByteString :: (Ptr Word8 -> Int -> IO Int) -> Int -> IO Lazy.ByteString
-buildByteString f k = lazyRead >>= return . Lazy.LPS
+buildByteString f k = lazyRead >>= return . Lazy.fromChunks
   where
     lazyRead = unsafeInterleaveIO $ do
         ps <- BSB.createAndTrim k $ \p -> f p k
@@ -285,11 +250,6 @@
 -- * Utilities
 --
 
--- | Run some action if the first action throws an exception.
---   The exception is re-thrown.
-onError :: IO a -> IO () -> IO a
-onError f h = f `Exception.catch` (\e -> h >> throwIO e)
-
 testReturn :: String -> IO CInt -> IO ()
 testReturn e = throwIfNeg_ (const $ e ++ " failed")
 
@@ -311,7 +271,11 @@
 -- * Debugging
 --
 
+{-# NOINLINE logMutex #-}
+logMutex :: MVar ()
+logMutex = unsafePerformIO (newMVar ())
+
 log :: String -> IO ()
 log msg = do
 	  t <- myThreadId
-	  hPutStrLn stderr (show t ++ ": " ++ msg)
+	  withMVar logMutex (const $ hPutStrLn stderr (show t ++ ": " ++ msg))
diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/usr/bin/env runghc
-
-import Distribution.Simple
-main = defaultMain
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,7 @@
+#!/usr/bin/env runghc
+
+> module Main where
+> import Distribution.Simple
+
+> main :: IO ()
+> main = defaultMain
diff --git a/fastcgi.cabal b/fastcgi.cabal
--- a/fastcgi.cabal
+++ b/fastcgi.cabal
@@ -1,17 +1,25 @@
 Name: fastcgi
-Version: 3000.0.0
-Copyright: Bjorn Bringert
-Maintainer: bjorn@bringert.net
-Author: Bjorn Bringert
-Homepage: http://www.cs.chalmers.se/~bringert/darcs/haskell-fastcgi/doc/
+Version: 3001.0.1
+Copyright: Bjorn Bringert, Lemmih
+Maintainer: lemmih@gmail.com
 License: BSD3
-build-depends: base>=2.0, cgi >= 3000.0.0
-Extensions: ForeignFunctionInterface
 Synopsis: A Haskell library for writing FastCGI programs
 Description:
  This library lets you write FastCGI programs. This package reuses the
  cgi package API, making it very easy to port CGI programs to FastCGI.
-Exposed-Modules: 
-   Network.FastCGI
-ghc-options: -O2
-extra-libraries: fcgi
+Cabal-version: >= 1.2.0
+
+flag small_base
+  description: Choose the new smaller, split-up base package.
+
+library
+  build-depends: cgi >= 3000.0.0
+  if flag(small_base)
+    build-depends:  base >= 3.0.0.0, bytestring >= 0.9.0.1
+  else
+    build-depends: base >= 2.0
+  Extensions: ForeignFunctionInterface, EmptyDataDecls
+  Exposed-Modules: 
+     Network.FastCGI
+  ghc-options: -O2 -Werror -fwarn-unused-binds -fwarn-unused-imports -fwarn-unused-matches
+  extra-libraries: fcgi
