This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "snap-server".

The branch, master has been updated
       via  05d2cb488d0d931a7e18def96caef4c8096734a8 (commit)
      from  cd3dc3ebe53f10a6c5f1a9321e5af489e6bff0f0 (commit)


Summary of changes:
 src/Snap/Http/Server.hs                        |    4 +-
 src/Snap/Http/Server/Config.hs                 |   90 +++++++++++++++--------
 src/Snap/Internal/Http/Server.hs               |   43 +++++++-----
 src/Snap/Internal/Http/Server/Backend.hs       |   13 ++--
 src/Snap/Internal/Http/Server/Date.hs          |    2 +-
 src/Snap/Internal/Http/Server/LibevBackend.hs  |   60 ++++++++++------
 src/Snap/Internal/Http/Server/SimpleBackend.hs |   53 ++++++++------
 src/Snap/Internal/Http/Server/TimeoutTable.hs  |    4 +-
 test/suite/Snap/Internal/Http/Server/Tests.hs  |   42 +++++++-----
 test/suite/Test/Blackbox.hs                    |    1 +
 10 files changed, 188 insertions(+), 124 deletions(-)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 05d2cb488d0d931a7e18def96caef4c8096734a8
Author: Gregory Collins <[email protected]>
Date:   Thu Jan 27 21:46:36 2011 +0100

    Expose timeout support to the user.

diff --git a/src/Snap/Http/Server.hs b/src/Snap/Http/Server.hs
index 8250161..b16af51 100644
--- a/src/Snap/Http/Server.hs
+++ b/src/Snap/Http/Server.hs
@@ -50,13 +50,15 @@ snapServerVersion = Int.snapServerVersion
 simpleHttpServe :: MonadSnap m => Config m a -> Snap () -> IO ()
 simpleHttpServe config handler = do
     setUnicodeLocale $ fromJust $ getLocale conf
-    Int.httpServe (map listenToInt $ getListen conf)
+    Int.httpServe tout
+                  (map listenToInt $ getListen conf)
                   (fmap backendToInt $ getBackend conf)
                   (fromJust $ getHostname  conf)
                   (fromJust $ getAccessLog conf)
                   (fromJust $ getErrorLog  conf)
                   (runSnap handler)
   where
+    tout = fromMaybe 60 $ getDefaultTimeout config
     conf = completeConfig config
     listenToInt (ListenHttp b p) = Int.HttpPort b p
     listenToInt (ListenHttps b p c k) = Int.HttpsPort b p c k
diff --git a/src/Snap/Http/Server/Config.hs b/src/Snap/Http/Server/Config.hs
index 99ab5f1..144ae43 100644
--- a/src/Snap/Http/Server/Config.hs
+++ b/src/Snap/Http/Server/Config.hs
@@ -26,6 +26,7 @@ module Snap.Http.Server.Config
   , getCompression
   , getVerbose
   , getErrorHandler
+  , getDefaultTimeout
   , getOther
 
   , setHostname
@@ -37,6 +38,7 @@ module Snap.Http.Server.Config
   , setCompression
   , setVerbose
   , setErrorHandler
+  , setDefaultTimeout
   , setOther
   ) where
 
@@ -94,25 +96,26 @@ data ConfigBackend = ConfigSimpleBackend
 -- Any fields which are unspecified in the 'Config' passed to 'httpServe' (and
 -- this is the norm) are filled in with default values from 'defaultConfig'.
 data MonadSnap m => Config m a = Config
-    { hostname     :: Maybe ByteString
+    { hostname       :: Maybe ByteString
       -- ^ The name of the server
-    , listen       :: [ConfigListen]
+    , listen         :: [ConfigListen]
       -- ^ The local interfaces to listen on
-    , accessLog    :: Maybe (Maybe FilePath)
+    , accessLog      :: Maybe (Maybe FilePath)
       -- ^ The path to the access log
-    , errorLog     :: Maybe (Maybe FilePath)
+    , errorLog       :: Maybe (Maybe FilePath)
       -- ^ The path to the error log
-    , locale       :: Maybe String
+    , locale         :: Maybe String
       -- ^ The locale to use
-    , backend      :: Maybe ConfigBackend
+    , backend        :: Maybe ConfigBackend
       -- ^ The backend to use
-    , compression  :: Maybe Bool
+    , compression    :: Maybe Bool
       -- ^ Whether to use compression
-    , verbose      :: Maybe Bool
+    , verbose        :: Maybe Bool
       -- ^ Whether to write server status updates to stderr
-    , errorHandler :: Maybe (SomeException -> m ())
+    , errorHandler   :: Maybe (SomeException -> m ())
       -- ^ A MonadSnap action to handle 500 errors
-    , other        :: Maybe a
+    , defaultTimeout :: Maybe Int
+    , other          :: Maybe a
       -- ^ This is for any other state needed to initialize a custom server
     }
 
@@ -129,6 +132,7 @@ instance MonadSnap m => Show (Config m a) where
         , showM "compression" . compression
         , showM "verbose" . verbose
         , showM "errorHandler" . fmap (const ()) . errorHandler
+        , showM "defaultTimeout" . fmap (const ()) . defaultTimeout
         ]) ++ "}"
       where
         showM s   = maybe "" ((++) (s ++ " = ") . show)
@@ -145,29 +149,31 @@ emptyConfig = mempty
 ------------------------------------------------------------------------------
 instance MonadSnap m => Monoid (Config m a) where
     mempty = Config
-        { hostname     = Nothing
-        , listen       = []
-        , accessLog    = Nothing
-        , errorLog     = Nothing
-        , locale       = Nothing
-        , backend      = Nothing
-        , compression  = Nothing
-        , verbose      = Nothing
-        , errorHandler = Nothing
-        , other        = Nothing
+        { hostname       = Nothing
+        , listen         = []
+        , accessLog      = Nothing
+        , errorLog       = Nothing
+        , locale         = Nothing
+        , backend        = Nothing
+        , compression    = Nothing
+        , verbose        = Nothing
+        , errorHandler   = Nothing
+        , defaultTimeout = Nothing
+        , other          = Nothing
         }
 
     a `mappend` b = Config
-        { hostname     = (hostname     b) `mplus` (hostname     a)
-        , listen       = (listen       b)   ++    (listen       a)
-        , accessLog    = (accessLog    b) `mplus` (accessLog    a)
-        , errorLog     = (errorLog     b) `mplus` (errorLog     a)
-        , locale       = (locale       b) `mplus` (locale       a)
-        , backend      = (backend      b) `mplus` (backend      a)
-        , compression  = (compression  b) `mplus` (compression  a)
-        , verbose      = (verbose      b) `mplus` (verbose      a)
-        , errorHandler = (errorHandler b) `mplus` (errorHandler a)
-        , other        = (other        b) `mplus` (other        a)
+        { hostname       = (hostname       b) `mplus` (hostname       a)
+        , listen         = (listen         b)   ++    (listen         a)
+        , accessLog      = (accessLog      b) `mplus` (accessLog      a)
+        , errorLog       = (errorLog       b) `mplus` (errorLog       a)
+        , locale         = (locale         b) `mplus` (locale         a)
+        , backend        = (backend        b) `mplus` (backend        a)
+        , compression    = (compression    b) `mplus` (compression    a)
+        , verbose        = (verbose        b) `mplus` (verbose        a)
+        , errorHandler   = (errorHandler   b) `mplus` (errorHandler   a)
+        , defaultTimeout = (defaultTimeout b) `mplus` (defaultTimeout a)
+        , other          = (other          b) `mplus` (other          a)
         }
 
 
@@ -202,6 +208,7 @@ defaultConfig = Config
                    . setResponseStatus 500 "Internal Server Error"
                    . modifyResponseBody (>==> enumBuilder (fromByteString msg))
                    $ emptyResponse
+    , defaultTimeout = Just 60
     , other        = Nothing
     }
 
@@ -231,6 +238,7 @@ data MonadSnap m => OptionData m a = OptionData
     , sslport :: Maybe Int
     , sslcert :: Maybe FilePath
     , sslkey  :: Maybe FilePath
+    , tout    :: Maybe Int
     }
 
 
@@ -244,6 +252,7 @@ instance MonadSnap m => Monoid (OptionData m a) where
         , sslport = Nothing
         , sslcert = Nothing
         , sslkey  = Nothing
+        , tout    = Nothing
         }
 
     a `mappend` b = OptionData
@@ -254,6 +263,7 @@ instance MonadSnap m => Monoid (OptionData m a) where
         , sslport      = (sslport      b) `mplus`   (sslport      a)
         , sslcert      = (sslcert      b) `mplus`   (sslcert      a)
         , sslkey       = (sslkey       b) `mplus`   (sslkey       a)
+        , tout         = (tout         b) `mplus`   (tout         a)
         }
 
 
@@ -268,13 +278,14 @@ defaultOptions = OptionData
     , sslport = Nothing
     , sslcert = Just "cert.pem"
     , sslkey  = Just "key.pem"
+    , tout    = Just 60
     }
 
 
 ------------------------------------------------------------------------------
 -- | Convert options to config
 optionsToConfig :: MonadSnap m => OptionData m a -> Config m a
-optionsToConfig o = mconcat $ [config o] ++ http ++ https
+optionsToConfig o = mconcat $ [config o] ++ http ++ https ++ [tmOut]
     where lhttp  = maybe2 [] ListenHttp  (bind o) (port o)
           lhttps = maybe4 [] ListenHttps (sslbind o)
                                          (sslport o)
@@ -288,6 +299,9 @@ optionsToConfig o = mconcat $ [config o] ++ http ++ https
           maybe4 _ f (Just a) (Just b) (Just c) (Just d) = [f a b c d]
           maybe4 d _ _        _        _        _        = d
 
+          tmOut = maybe mempty
+                        (\t -> mempty { defaultTimeout = Just t })
+                        (tout o)
 
 ------------------------------------------------------------------------------
 -- | Convert config to options
@@ -300,6 +314,7 @@ configToOptions c = OptionData
     , sslport = Nothing
     , sslcert = Nothing
     , sslkey  = Nothing
+    , tout    = (defaultTimeout c)
     }
 
 
@@ -359,6 +374,9 @@ options defaults =
     , Option ['c'] ["compression"]
              (NoArg $ Just $ setConfig setCompression True)
              $ "use gzip compression on responses"
+    , Option ['t'] ["timeout"]
+             (ReqArg (\t -> Just $ mempty { tout = Just $ read t}) "SECS")
+             $ "set default timeout in seconds"
     , Option [] ["no-compression"]
              (NoArg $ Just $ setConfig setCompression False)
              $ "serve responses uncompressed"
@@ -469,6 +487,11 @@ getOther = other
 
 
 ------------------------------------------------------------------------------
+getDefaultTimeout :: MonadSnap m => Config m a -> Maybe Int
+getDefaultTimeout = defaultTimeout
+
+
+------------------------------------------------------------------------------
 setHostname :: MonadSnap m => ByteString -> Config m a -> Config m a
 setHostname a m = m {hostname = Just a}
 
@@ -517,3 +540,8 @@ setErrorHandler a m = m {errorHandler = Just a}
 ------------------------------------------------------------------------------
 setOther :: MonadSnap m => a -> Config m a -> Config m a
 setOther a m = m {other = Just a}
+
+
+------------------------------------------------------------------------------
+setDefaultTimeout :: MonadSnap m => Int -> Config m a -> Config m a
+setDefaultTimeout t m = m {defaultTimeout = Just t}
diff --git a/src/Snap/Internal/Http/Server.hs b/src/Snap/Internal/Http/Server.hs
index 086733f..d67714d 100644
--- a/src/Snap/Internal/Http/Server.hs
+++ b/src/Snap/Internal/Http/Server.hs
@@ -64,8 +64,9 @@ import qualified Paths_snap_server as V
 -- Note that we won't be bothering end users with this -- the details will be
 -- hidden inside the Snap monad
 type ServerHandler = (ByteString -> IO ())
-                   -> Request
-                   -> Iteratee ByteString IO (Request,Response)
+                  -> (Int -> IO ())
+                  -> Request
+                  -> Iteratee ByteString IO (Request,Response)
 
 
 ------------------------------------------------------------------------------
@@ -122,7 +123,8 @@ runServerMonad lh s la le m = evalStateT m st
 
 
 ------------------------------------------------------------------------------
-httpServe :: [ListenPort]        -- ^ ports to listen on
+httpServe :: Int                 -- ^ default timeout
+          -> [ListenPort]        -- ^ ports to listen on
           -> Maybe EventLoopType -- ^ Specify a given event loop,
                                  --   otherwise a default is picked
           -> ByteString          -- ^ local hostname (server name)
@@ -130,7 +132,8 @@ httpServe :: [ListenPort]        -- ^ ports to listen on
           -> Maybe FilePath      -- ^ path to the error log
           -> ServerHandler       -- ^ handler procedure
           -> IO ()
-httpServe ports mevType localHostname alogPath elogPath handler =
+httpServe defaultTimeout ports mevType localHostname alogPath elogPath
+          handler =
     withLoggers alogPath elogPath
                 (\(alog, elog) -> spawnAll alog elog)
 
@@ -152,9 +155,9 @@ httpServe ports mevType localHostname alogPath elogPath 
handler =
 
         nports <- mapM bindPort ports
 
-        (runEventLoop evType nports numCapabilities (logE elog) $
-                      runHTTP alog elog handler localHostname) `finally` do
-
+        (runEventLoop evType defaultTimeout nports numCapabilities (logE elog)
+                      $ runHTTP defaultTimeout alog elog handler localHostname)
+          `finally` do
             logE elog "Server.httpServe: SHUTDOWN"
 
             if initHttps
@@ -233,7 +236,8 @@ logA' logger req rsp = do
 
 
 ------------------------------------------------------------------------------
-runHTTP :: Maybe Logger                  -- ^ access logger
+runHTTP :: Int                           -- ^ default timeout
+        -> Maybe Logger                  -- ^ access logger
         -> Maybe Logger                  -- ^ error logger
         -> ServerHandler                 -- ^ handler procedure
         -> ByteString                    -- ^ local host name
@@ -242,9 +246,10 @@ runHTTP :: Maybe Logger                  -- ^ access logger
         -> Iteratee ByteString IO ()     -- ^ write end of socket
         -> (FilePath -> Int64 -> Int64 -> IO ())
                                          -- ^ sendfile end
-        -> IO ()                         -- ^ timeout tickler
+        -> (Int -> IO ())                -- ^ timeout tickler
         -> IO ()
-runHTTP alog elog handler lh sinfo readEnd writeEnd onSendFile tickle =
+runHTTP defaultTimeout alog elog handler lh sinfo readEnd writeEnd onSendFile
+        tickle =
     go `catches` [ Handler $ \(e :: AsyncException) -> do
                        throwIO e
 
@@ -257,8 +262,8 @@ runHTTP alog elog handler lh sinfo readEnd writeEnd 
onSendFile tickle =
     go = do
         buf <- allocBuffer 16384
         let iter1 = runServerMonad lh sinfo (logA alog) (logE elog) $
-                                   httpSession writeEnd buf onSendFile tickle
-                                   handler
+                                   httpSession defaultTimeout writeEnd buf
+                                               onSendFile tickle handler
         let iter = iterateeDebugWrapper "httpSession iteratee" iter1
 
         debug "runHTTP/go: prepping iteratee for start"
@@ -292,14 +297,15 @@ logError s = gets _logError >>= (\l -> liftIO $ l s)
 
 ------------------------------------------------------------------------------
 -- | Runs an HTTP session.
-httpSession :: Iteratee ByteString IO ()     -- ^ write end of socket
+httpSession :: Int
+            -> Iteratee ByteString IO ()     -- ^ write end of socket
             -> Buffer                        -- ^ builder buffer
             -> (FilePath -> Int64 -> Int64 -> IO ())
                                              -- ^ sendfile continuation
-            -> IO ()                         -- ^ timeout tickler
+            -> (Int -> IO ())                -- ^ timeout tickler
             -> ServerHandler                 -- ^ handler procedure
             -> ServerMonad ()
-httpSession writeEnd' buffer onSendFile tickle handler = do
+httpSession defaultTimeout writeEnd' buffer onSendFile tickle handler = do
 
     let writeEnd = iterateeDebugWrapper "writeEnd" writeEnd'
 
@@ -308,7 +314,7 @@ httpSession writeEnd' buffer onSendFile tickle handler = do
     liftIO $ debug "Server.httpSession: receiveRequest finished"
 
     -- successfully got a request, so restart timer
-    liftIO tickle
+    liftIO $ tickle defaultTimeout
 
     case mreq of
       (Just req) -> do
@@ -322,7 +328,7 @@ httpSession writeEnd' buffer onSendFile tickle handler = do
 
           logerr <- gets _logError
 
-          (req',rspOrig) <- lift $ handler logerr req
+          (req',rspOrig) <- lift $ handler logerr tickle req
 
           liftIO $ debug $ "Server.httpSession: finished running user handler"
 
@@ -368,7 +374,8 @@ httpSession writeEnd' buffer onSendFile tickle handler = do
              then do
                  debug $ "httpSession: Connection: Close, harikari"
                  liftIO $ myThreadId >>= killThread
-             else httpSession writeEnd' buffer onSendFile tickle handler
+             else httpSession defaultTimeout writeEnd' buffer onSendFile tickle
+                              handler
 
       Nothing -> do
           liftIO $ debug $ "Server.httpSession: parser did not produce a " ++
diff --git a/src/Snap/Internal/Http/Server/Backend.hs 
b/src/Snap/Internal/Http/Server/Backend.hs
index 3791724..1364eb3 100644
--- a/src/Snap/Internal/Http/Server/Backend.hs
+++ b/src/Snap/Internal/Http/Server/Backend.hs
@@ -36,16 +36,17 @@ type SessionHandler =
     -> Enumerator ByteString IO ()           -- ^ read end of socket
     -> Iteratee ByteString IO ()             -- ^ write end of socket
     -> (FilePath -> Int64 -> Int64 -> IO ()) -- ^ sendfile end
-    -> IO ()                                 -- ^ timeout tickler
+    -> (Int -> IO ())                        -- ^ timeout tickler
     -> IO ()
 
 
 ------------------------------------------------------------------------------
-type EventLoop = [ListenSocket]                -- ^ list of ports
-               -> Int                          -- ^ number of capabilities
-               -> (ByteString -> IO ())        -- ^ error log
-               -> SessionHandler               -- ^ session handler
-               -> IO ()
+type EventLoop = Int                       -- ^ default timeout
+              -> [ListenSocket]            -- ^ list of ports
+              -> Int                       -- ^ number of capabilities
+              -> (ByteString -> IO ())     -- ^ error log
+              -> SessionHandler            -- ^ session handler
+              -> IO ()
 
 
 {- For performance reasons, we do not implement this as a class
diff --git a/src/Snap/Internal/Http/Server/Date.hs 
b/src/Snap/Internal/Http/Server/Date.hs
index 3d68f1b..0e0b09a 100644
--- a/src/Snap/Internal/Http/Server/Date.hs
+++ b/src/Snap/Internal/Http/Server/Date.hs
@@ -102,7 +102,7 @@ dateThread ds@(DateState _ _ _ valueIsOld morePlease _) = 
loop
 ensureFreshDate :: IO ()
 ensureFreshDate = block $ do
     old <- readIORef $ _valueIsOld dateState
-    tryPutMVar (_morePlease dateState) ()
+    _ <- tryPutMVar (_morePlease dateState) ()
 
     -- if the value is not fresh we will tickle the date thread but also fetch
     -- the new value immediately; we used to block but we'll do a little extra
diff --git a/src/Snap/Internal/Http/Server/LibevBackend.hs 
b/src/Snap/Internal/Http/Server/LibevBackend.hs
index 803038e..c2d463b 100644
--- a/src/Snap/Internal/Http/Server/LibevBackend.hs
+++ b/src/Snap/Internal/Http/Server/LibevBackend.hs
@@ -22,7 +22,7 @@ data LibevException = LibevException String
 instance Exception LibevException
 
 libEvEventLoop :: EventLoop
-libEvEventLoop _ _ _ _ = throwIO $
+libEvEventLoop _ _ _ _ _ = throwIO $
     LibevException "libev event loop is not supported"
 
 #else
@@ -107,8 +107,9 @@ data Connection = Connection
 
 ------------------------------------------------------------------------------
 libEvEventLoop :: EventLoop
-libEvEventLoop sockets cap elog handler = do
-    backends <- Prelude.mapM (newLoop sockets handler elog) [0..(cap-1)]
+libEvEventLoop defaultTimeout sockets cap elog handler = do
+    backends <- Prelude.mapM (newLoop defaultTimeout sockets handler elog)
+                             [0..(cap-1)]
 
     debug "libevEventLoop: waiting for loop exit"
     Prelude.mapM_ (takeMVar . _loopExit) backends `finally` do
@@ -118,12 +119,13 @@ libEvEventLoop sockets cap elog handler = do
 
 
 ------------------------------------------------------------------------------
-newLoop :: [ListenSocket]        -- ^ value you got from bindIt
+newLoop :: Int                   -- ^ default timeout
+        -> [ListenSocket]        -- ^ value you got from bindIt
         -> SessionHandler        -- ^ handler
         -> (ByteString -> IO ()) -- ^ error logger
         -> Int                   -- ^ cpu
         -> IO Backend
-newLoop sockets handler elog cpu = do
+newLoop defaultTimeout sockets handler elog cpu = do
     -- We'll try kqueue on OSX even though the libev docs complain that it's
     -- "broken", in the hope that it works as expected for sockets
     f  <- evRecommendedBackends
@@ -179,7 +181,8 @@ newLoop sockets handler elog cpu = do
     -- setup the accept callback; this watches for read readiness on the
     -- listen port
     forM_ (zip3 sockets accIOs accMVars) $ \(sock, accIO, x) -> do
-        accCB <- mkIoCallback $ acceptCallback b handler elog cpu sock
+        accCB <- mkIoCallback $ acceptCallback defaultTimeout b handler elog
+                                               cpu sock
         evIoInit accIO accCB (fdSocket $ Listen.listenSocket sock) ev_read
         evIoStart lp accIO
         putMVar x accCB
@@ -209,13 +212,14 @@ loopThread backend = do
 
 
 ------------------------------------------------------------------------------
-acceptCallback :: Backend
+acceptCallback :: Int
+               -> Backend
                -> SessionHandler
                -> (ByteString -> IO ())
                -> Int
                -> ListenSocket
                -> IoCallback
-acceptCallback back handler elog cpu sock _loopPtr _ioPtr _ = do
+acceptCallback defaultTimeout back handler elog cpu sock _loopPtr _ioPtr _ = do
     debug "inside acceptCallback"
     r <- c_accept $ fdSocket $ Listen.listenSocket sock
 
@@ -230,7 +234,7 @@ acceptCallback back handler elog cpu sock _loopPtr _ioPtr _ 
= do
           forkOnIO cpu $ (go r `catches` cleanup)
           return ()
   where
-    go = runSession back handler sock
+    go = runSession defaultTimeout back handler sock
     cleanup = [ Handler $ \(_ :: TimeoutException) -> return ()
               , Handler $ \(e :: SomeException) ->
                   elog $ S.concat [ "libev.acceptCallback: "
@@ -436,12 +440,13 @@ freeBackend backend = ignoreException $ block $ do
 
 ------------------------------------------------------------------------------
 -- | Note: proc gets run in the background
-runSession :: Backend
+runSession :: Int
+           -> Backend
            -> SessionHandler
            -> ListenSocket
            -> CInt
            -> IO ()
-runSession backend handler lsock fd = do
+runSession defaultTimeout backend handler lsock fd = do
     sock <- mkSocket fd AF_INET Stream 0 Connected
     peerName <- getPeerName sock
     sockName <- getSocketName sock
@@ -527,8 +532,8 @@ runSession backend handler lsock fd = do
             (\session -> do H.update tid conn (_connectionThreads backend)
                             handler sinfo
                                     (enumerate conn session)
-                                    (writeOut conn session)
-                                    (sendFile conn session)
+                                    (writeOut defaultTimeout conn session)
+                                    (sendFile defaultTimeout conn session)
                                     (tickleTimeout conn)
             )
 
@@ -573,11 +578,11 @@ instance Exception TimeoutException
 
 
 ------------------------------------------------------------------------------
-tickleTimeout :: Connection -> IO ()
-tickleTimeout conn = do
+tickleTimeout :: Connection -> Int -> IO ()
+tickleTimeout conn tm = do
     debug "Libev.tickleTimeout"
     now       <- getCurrentDateTime
-    writeIORef (_timerTimeoutTime conn) (now + 30)
+    writeIORef (_timerTimeoutTime conn) (now + toEnum tm)
 
 
 ------------------------------------------------------------------------------
@@ -621,9 +626,14 @@ waitForLock readLock conn = do
 
 
 ------------------------------------------------------------------------------
-sendFile :: Connection -> NetworkSession -> FilePath -> Int64 -> Int64
+sendFile :: Int
+         -> Connection
+         -> NetworkSession
+         -> FilePath
+         -> Int64
+         -> Int64
          -> IO ()
-sendFile c s fp start sz = do
+sendFile defaultTimeout c s fp start sz = do
     withMVar lock $ \_ -> do
       act <- readIORef $ _writeActive c
       when act $ evIoStop loop io
@@ -636,10 +646,10 @@ sendFile c s fp start sz = do
                                 (closeFd)
                                 (go start sz)
         _            -> do
-            step <- runIteratee $ writeOut c s
+            step <- runIteratee $ writeOut defaultTimeout c s
             run_ $ enumFilePartial fp (start,start+sz) step
 #else
-    step <- runIteratee $ writeOut c s
+    step <- runIteratee $ writeOut defaultTimeout c s
 
     run_ $ enumFilePartial fp (start,start+sz) step
     return ()
@@ -657,7 +667,8 @@ sendFile c s fp start sz = do
       | otherwise  = do
             sent <- SF.sendFile sfd fd off bytes
             if sent < bytes
-              then tickleTimeout c >> go (off+sent) (bytes-sent) fd
+              then tickleTimeout c defaultTimeout >>
+                   go (off+sent) (bytes-sent) fd
               else return ()
 
     sfd  = Fd $ _rawSocket c
@@ -707,10 +718,11 @@ enumerate conn session = loop
 
 ------------------------------------------------------------------------------
 writeOut :: (MonadIO m)
-         => Connection
+         => Int
+         -> Connection
          -> NetworkSession
          -> Iteratee ByteString m ()
-writeOut conn session = loop
+writeOut defaultTimeout conn session = loop
   where
     loop = continue k
 
@@ -720,7 +732,7 @@ writeOut conn session = loop
         loop
 
     sendData = Listen.send (_listenSocket conn)
-                           (tickleTimeout conn)
+                           (tickleTimeout conn defaultTimeout)
                            (waitForLock False conn)
                            session
 
diff --git a/src/Snap/Internal/Http/Server/SimpleBackend.hs 
b/src/Snap/Internal/Http/Server/SimpleBackend.hs
index 32b1269..ea2b84a 100644
--- a/src/Snap/Internal/Http/Server/SimpleBackend.hs
+++ b/src/Snap/Internal/Http/Server/SimpleBackend.hs
@@ -63,29 +63,31 @@ data EventLoopCpu = EventLoopCpu
 
 ------------------------------------------------------------------------------
 simpleEventLoop :: EventLoop
-simpleEventLoop sockets cap elog handler = do
-    loops <- Prelude.mapM (newLoop sockets handler elog) [0..(cap-1)]
+simpleEventLoop defaultTimeout sockets cap elog handler = do
+    loops <- Prelude.mapM (newLoop defaultTimeout sockets handler elog)
+                          [0..(cap-1)]
 
     debug "simpleEventLoop: waiting for mvars"
 
     --wait for all threads to exit
     Prelude.mapM_ (takeMVar . _exitMVar) loops `finally` do
         debug "simpleEventLoop: killing all threads"
-        mapM stopLoop loops
-        mapM Listen.closeSocket sockets
+        _ <- mapM_ stopLoop loops
+        mapM_ Listen.closeSocket sockets
 
 
 ------------------------------------------------------------------------------
-newLoop :: [ListenSocket]
+newLoop :: Int
+        -> [ListenSocket]
         -> SessionHandler
         -> (S.ByteString -> IO ())
         -> Int
         -> IO EventLoopCpu
-newLoop sockets handler elog cpu = do
+newLoop defaultTimeout sockets handler elog cpu = do
     tt         <- TT.new
     exit       <- newEmptyMVar
     accThreads <- forM sockets $ \p -> forkOnIO cpu $
-                  acceptThread handler tt elog cpu p
+                  acceptThread defaultTimeout handler tt elog cpu p
     tid        <- forkOnIO cpu $ timeoutThread tt exit
 
     return $ EventLoopCpu cpu accThreads tt tid exit
@@ -99,22 +101,23 @@ stopLoop loop = block $ do
 
 
 ------------------------------------------------------------------------------
-acceptThread :: SessionHandler
+acceptThread :: Int
+             -> SessionHandler
              -> TimeoutTable
              -> (S.ByteString -> IO ())
              -> Int
              -> ListenSocket
              -> IO ()
-acceptThread handler tt elog cpu sock = loop
+acceptThread defaultTimeout handler tt elog cpu sock = loop
   where
     loop = do
         debug $ "acceptThread: calling accept() on socket " ++ show sock
         (s,addr) <- accept $ Listen.listenSocket sock
         debug $ "acceptThread: accepted connection from remote: " ++ show addr
-        forkOnIO cpu (go s addr `catches` cleanup)
+        _ <- forkOnIO cpu (go s addr `catches` cleanup)
         loop
 
-    go = runSession handler tt sock
+    go = runSession defaultTimeout handler tt sock
 
     cleanup =
         [
@@ -141,10 +144,7 @@ timeoutThread table exitMVar = do
 
     killTooOld = do
         now    <- getCurrentDateTime
-        TT.killOlderThan (now - tIMEOUT) table
-
-    -- timeout = 30 seconds
-    tIMEOUT = 30
+        TT.killOlderThan now table
 
     killAll = do
         debug "Backend.timeoutThread: shutdown, killing all connections"
@@ -162,9 +162,13 @@ instance Exception AddressNotSupportedException
 
 
 ------------------------------------------------------------------------------
-runSession :: SessionHandler -> TimeoutTable -> ListenSocket -> Socket
+runSession :: Int
+           -> SessionHandler
+           -> TimeoutTable
+           -> ListenSocket
+           -> Socket
            -> SockAddr -> IO ()
-runSession handler tt lsock sock addr = do
+runSession defaultTimeout handler tt lsock sock addr = do
     let fd = fdSocket sock
     curId <- myThreadId
 
@@ -191,7 +195,7 @@ runSession handler tt lsock sock addr = do
     let curHash = hashString $ show curId
     let timeout = tickleTimeout tt curId curHash
 
-    timeout
+    timeout defaultTimeout
 
     bracket (Listen.createSession lsock 8192 fd
               (threadWaitRead $ fromIntegral fd))
@@ -205,11 +209,12 @@ runSession handler tt lsock sock addr = do
                  eatException $ shutdown sock ShutdownBoth
                  eatException $ sClose sock
             )
-            (\s -> let writeEnd = writeOut lsock s sock timeout
+            (\s -> let writeEnd = writeOut lsock s sock (timeout 
defaultTimeout)
                    in handler sinfo
                               (enumerate lsock s sock)
                               writeEnd
-                              (sendFile lsock timeout fd writeEnd)
+                              (sendFile lsock (timeout defaultTimeout) fd
+                                        writeEnd)
                               timeout
             )
 
@@ -257,11 +262,11 @@ sendFile _ _ _ writeEnd fp start sz = do
 
 
 ------------------------------------------------------------------------------
-tickleTimeout :: TimeoutTable -> ThreadId -> Word -> IO ()
-tickleTimeout table tid thash = do
+tickleTimeout :: TimeoutTable -> ThreadId -> Word -> Int -> IO ()
+tickleTimeout table tid thash tm = do
     debug "Backend.tickleTimeout"
     now   <- getCurrentDateTime
-    TT.insert thash tid now table
+    TT.insert thash tid (now + toEnum tm) table
 
 
 ------------------------------------------------------------------------------
@@ -321,7 +326,7 @@ writeOut :: (MonadIO m)
          => ListenSocket
          -> NetworkSession
          -> Socket
-         -> IO ()
+         -> (IO ())
          -> Iteratee ByteString m ()
 writeOut port session sock tickle = loop
   where
diff --git a/src/Snap/Internal/Http/Server/TimeoutTable.hs 
b/src/Snap/Internal/Http/Server/TimeoutTable.hs
index b46ddc0..699fefd 100644
--- a/src/Snap/Internal/Http/Server/TimeoutTable.hs
+++ b/src/Snap/Internal/Http/Server/TimeoutTable.hs
@@ -73,7 +73,7 @@ insert thash tid time (TimeoutTable maps act) = do
         let !psq' = PSQ.insert tid time psq
         return $! psq'
 
-    tryPutMVar act ()
+    _ <- tryPutMVar act ()
     return ()
 
   where
@@ -88,7 +88,7 @@ delete thash tid (TimeoutTable maps act) = do
         let !psq' = PSQ.delete tid psq
         return $! psq'
 
-    tryPutMVar act ()
+    _ <- tryPutMVar act ()
     return ()
 
   where
diff --git a/test/suite/Snap/Internal/Http/Server/Tests.hs 
b/test/suite/Snap/Internal/Http/Server/Tests.hs
index 1d50557..a855b5a 100644
--- a/test/suite/Snap/Internal/Http/Server/Tests.hs
+++ b/test/suite/Snap/Internal/Http/Server/Tests.hs
@@ -514,9 +514,10 @@ testHttpResponseCookies = testCase 
"server/HttpResponseCookies" $ do
 
 
 echoServer :: (ByteString -> IO ())
+           -> (Int -> IO ())
            -> Request
            -> Iteratee ByteString IO (Request,Response)
-echoServer _ req = do
+echoServer _ _ req = do
     se <- liftIO $ readIORef (rqBody req)
     let (SomeEnumerator enum) = se
     i <- liftM enum $ lift $ runIteratee copyingStream2Stream
@@ -531,8 +532,8 @@ echoServer _ req = do
 
 
 echoServer2 :: ServerHandler
-echoServer2 _ req = do
-    (rq,rsp) <- echoServer (const $ return ()) req
+echoServer2 _ _ req = do
+    (rq,rsp) <- echoServer (const $ return ()) (const $ return ()) req
     return (rq, addResponseCookie cook rsp)
   where
     cook = Cookie "foo" "bar" (Just utc) (Just ".foo.com") (Just "/")
@@ -547,8 +548,9 @@ testHttp1 = testCase "server/httpSession" $ do
 
     let (iter,onSendFile) = mkIter ref
 
-    runHTTP Nothing Nothing echoServer "localhost" (SessionInfo "127.0.0.1" 80 
"127.0.0.1" 58384 False)
-            enumBody iter onSendFile (return ())
+    runHTTP 60 Nothing Nothing echoServer "localhost"
+            (SessionInfo "127.0.0.1" 80 "127.0.0.1" 58384 False)
+            enumBody iter onSendFile (const $ return ())
 
     s <- readIORef ref
 
@@ -601,8 +603,9 @@ testChunkOn1_0 = testCase "server/transfer-encoding 
chunked" $ do
     let (iter,onSendFile) = mkIter ref
 
     done <- newEmptyMVar
-    forkIO (runHTTP Nothing Nothing f "localhost" (SessionInfo "127.0.0.1" 80 
"127.0.0.1" 58384 False)
-                enumBody iter onSendFile (return ())
+    forkIO (runHTTP 60 Nothing Nothing f "localhost"
+                    (SessionInfo "127.0.0.1" 80 "127.0.0.1" 58384 False)
+                enumBody iter onSendFile (const $ return ())
             `finally` putMVar done ())
 
     takeMVar done
@@ -618,7 +621,7 @@ testChunkOn1_0 = testCase "server/transfer-encoding 
chunked" $ do
     lower = S.map toLower . S.concat . L.toChunks
 
     f :: ServerHandler
-    f _ req = do
+    f _ _ req = do
         let s = L.fromChunks $ Prelude.take 500 $ repeat "fldkjlfksdjlfd"
         let out = enumBuilder $ fromLazyByteString s
         return (req, emptyResponse { rspBody = Enum out })
@@ -646,7 +649,8 @@ testHttp2 = testCase "server/connection: close" $ do
 
     done <- newEmptyMVar
 
-    forkIO (runHTTP Nothing
+    forkIO (runHTTP 60
+                    Nothing
                     Nothing
                     echoServer2
                     "localhost"
@@ -654,7 +658,7 @@ testHttp2 = testCase "server/connection: close" $ do
                     enumBody
                     iter
                     onSendFile
-                    (return ()) `finally` putMVar done ())
+                    (const $ return ()) `finally` putMVar done ())
 
     takeMVar done
 
@@ -687,7 +691,8 @@ testHttp100 = testCase "server/expect100" $ do
 
     let (iter,onSendFile) = mkIter ref
 
-    runHTTP Nothing
+    runHTTP 60
+            Nothing
             Nothing
             echoServer2
             "localhost"
@@ -695,7 +700,7 @@ testHttp100 = testCase "server/expect100" $ do
             enumBody
             iter
             onSendFile
-            (return ())
+            (const $ return ())
 
     s <- readIORef ref
 
@@ -730,7 +735,8 @@ testExpectGarbage = testCase "server/Expect: garbage" $ do
 
     let (iter,onSendFile) = mkIter ref
 
-    runHTTP Nothing
+    runHTTP 60
+            Nothing
             Nothing
             echoServer2
             "localhost"
@@ -738,7 +744,7 @@ testExpectGarbage = testCase "server/Expect: garbage" $ do
             enumBody
             iter
             onSendFile
-            (return ())
+            (const $ return ())
 
     s <- readIORef ref
 
@@ -783,7 +789,7 @@ testSendFile = testCase "server/sendFile" $ do
                        m)
 
   where
-    serve = (httpServe [HttpPort "*" port] Nothing "localhost"
+    serve = (httpServe 60 [HttpPort "*" port] Nothing "localhost"
                        Nothing Nothing
                     $ runSnap sendFileFoo)
             `catch` \(_::SomeException) -> return ()
@@ -807,7 +813,8 @@ testSendFile = testCase "server/sendFile" $ do
 testServerStartupShutdown :: Test
 testServerStartupShutdown = testCase "server/startup/shutdown" $ do
     bracket (forkIO $
-             httpServe [HttpPort "*" port]
+             httpServe 20
+                       [HttpPort "*" port]
                        Nothing
                        "localhost"
                        (Just "test-access.log")
@@ -845,7 +852,8 @@ testServerStartupShutdown = testCase 
"server/startup/shutdown" $ do
 testServerShutdownWithOpenConns :: Test
 testServerShutdownWithOpenConns = testCase "server/shutdown-open-conns" $ do
     tid <- forkIO $
-           httpServe [HttpPort "127.0.0.1" port]
+           httpServe 20
+                     [HttpPort "127.0.0.1" port]
                      Nothing
                      "localhost"
                      Nothing
diff --git a/test/suite/Test/Blackbox.hs b/test/suite/Test/Blackbox.hs
index 8a58a1f..746050a 100644
--- a/test/suite/Test/Blackbox.hs
+++ b/test/suite/Test/Blackbox.hs
@@ -67,6 +67,7 @@ startTestServer port sslport backend = do
               setErrorLog  (Just $ "ts-error." ++ show backend ++ ".log")  .
               addListen    (ListenHttp "*" port)                           .
               setBackend   backend                                         .
+              setDefaultTimeout 10                                         .
               setVerbose   False                                           $
               defaultConfig
 
-----------------------------------------------------------------------


hooks/post-receive
-- 
snap-server
_______________________________________________
Snap mailing list
[email protected]
http://mailman-mail5.webfaction.com/listinfo/snap

Reply via email to