-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Daemons in Haskell made fun and easy -- -- Control.Pipe.C3 provides simple RPC-like wrappers for pipes. -- -- Control.Pipe.Serialize provides serialization and incremental -- deserialization pipes. -- -- Control.Pipe.Socket provides functions to setup pipes around -- sockets. -- -- System.Daemon provides a high-level interface to starting -- daemonized programs that are controlled through sockets. -- -- System.Posix.Daemon provides a low-level interface to starting, -- and controlling detached jobs. -- -- See the README.md file and the homepage for details. @package daemons @version 0.2.0 -- | This module provides a simple interface to creating, checking the -- status of, and stopping background jobs. -- -- Use runDetached to start a background job. For instance, here -- is a daemon that peridically hits a webserver: -- --
--   import Control.Concurrent
--   import Control.Monad
--   import Data.Default
--   import Data.Maybe
--   import Network.BSD
--   import Network.HTTP
--   import Network.URI
--   import System.Posix.Daemon
--   
--   main :: IO ()
--   main = runDetached (Just "diydns.pid") def $ forever $ do
--       hostname <- getHostName
--       _ <- simpleHTTP
--                (Request { rqURI     = fromJust (parseURI "http://foo.com/dns")
--                         , rqMethod  = GET
--                         , rqHeaders = []
--                         , rqBody    = hostname })
--       threadDelay (600 * 1000 * 1000)
--   
-- -- To check if the above job is running, use isRunning with the -- same pidfile: -- --
--   isRunning "diydns.pid"
--   
-- -- Finally, to stop the above job (maybe because we're rolling a new -- version of it), use kill: -- --
--   kill "diydns.pid"
--   
-- -- To stop a job and wait for it to close (and release its pidfile), use -- killAndWait: -- --
--   killAndWait "diydns.pid" >> doSomething
--   
-- -- As a side note, the code above is a script that the author uses as a -- sort of homebrew dynamic DNS: the remote address is a CGI script that -- records the IP addresses of all incoming requests in separate files -- named after the contents of the requests; the addresses are then -- viewable with any browser. module System.Posix.Daemon -- | Run the given action detached from the current terminal; this creates -- an entirely new process. This function returns immediately. Uses the -- double-fork technique to create a well behaved daemon. If -- pidfile is given, check/write it; if we cannot obtain a lock -- on the file, another process is already using it, so fail. The -- redirection parameter controls what to do with the standard -- channels (stdin, stderr, and stdout). -- -- See: http://www.enderunix.org/docs/eng/daemon.php -- -- Note: All unnecessary fds should be close before calling this. -- Otherwise, you get an fd leak. runDetached :: Maybe FilePath -> Redirection -> IO () -> IO () -- | Where should the output (and input) of a daemon be redirected to? (we -- can't just leave it to the current terminal, because it may be closed, -- and that would kill the daemon). -- -- When in doubt, just use def, the default value. -- -- DevNull causes the output to be redirected to -- /dev/null. This is safe and is what you want in most cases. -- -- If you don't want to lose the output (maybe because you're using it -- for logging), use ToFile, instead. data Redirection DevNull :: Redirection ToFile :: FilePath -> Redirection -- | Return True if the given file is locked by a process. In our -- case, returns True when the daemon that created the file is -- still alive. isRunning :: FilePath -> IO Bool -- | Send sigQUIT to the process recorded in the pidfile. This gives -- the process a chance to close cleanly. kill :: FilePath -> IO () -- | Kill a process and wait for it to release its pidfile killAndWait :: FilePath -> IO () -- | Send sigKILL to the process recorded in the pidfile. This -- immediately kills the process. brutalKill :: FilePath -> IO () instance Show Redirection instance Default Redirection module Control.Pipe.Socket -- | Stream data from the socket. socketReader :: MonadIO m => Socket -> Producer ByteString m () -- | Stream data to the socket. socketWriter :: MonadIO m => Socket -> Consumer ByteString m () -- | A simple handler: takes an incoming stream of ByteStrings, an -- stream of ByteStrings, and ties them together somehow. -- Conceptually, the simplest handler would be identity: -- --
--   import Control.Monad
--   import Control.Pipe
--   import Data.ByteString.Char8
--   
--   handler reader writer = do
--       let identity = forever $ do
--           x <- await
--           yield x
--       runPipe (writer <+< identity <+< reader)
--   
-- -- See the pipes tutorial for more examples of writing pipes. -- -- Since ByteStrings are fairly boring by themseleves, have a look -- at Control.Pipe.Serialize which lets you deserialize/serialize -- pipes of ByteStrings easily. type Handler r = Producer ByteString IO () -> Consumer ByteString IO () -> IO r -- | Listen for connections on the given socket, and run Handler on -- each received connection. The socket should previously have been bound -- to a port or to a file. Each handler is run in its own thread. Even in -- case of an error, the handlers' sockets are closed. runSocketServer :: MonadIO m => Socket -> Handler () -> m () -- | Run Handler on the given socket. runSocketClient :: MonadIO m => Socket -> Handler r -> m r -- | This module provides the deserializer and serializer -- pipes to convert ByteStrings off of pipes into typed values. -- -- In order to use it, the types of the values need to have -- Serialize instances. These can be derived automatically using -- Ghc.Generics: -- --
--   {-# LANGUAGE DeriveGeneric #-}
--   
--   data Foo = Bar String | Baz Int
--              deriving ( Generic )
--   
--   instance Serialize Foo
--   
-- -- Note that in the above example: we use the DeriveGeneric -- extension, derive a Generic instance for our data-type, and -- write an empty Serialize instance. module Control.Pipe.Serialize -- | Serialize data into strict ByteStrings. serializer :: (Serialize a, Monad m) => Pipe a ByteString m () -- | De-serialize data from strict ByteStrings. Uses -- cereal's incremental Get parser. deserializer :: (Serialize a, Monad m) => Pipe ByteString a m () module Control.Pipe.C3 -- | Send a single command over the outgoing pipe and wait for a response. -- If the incoming pipe is closed before a response arrives, returns -- Nothing. commandSender :: (Serialize a, Serialize b) => a -> Handler (Maybe b) -- | Wait for commands on the incoming pipe, handle them, and send the -- reponses over the outgoing pipe. commandReceiver :: (Serialize a, Serialize b) => (a -> IO b) -> Handler () -- | An RPC-like interface for daemons is provided by -- ensureDaemonRunning and runClient. -- -- A more versatile interface that lets you supply your own -- Handler is provided by ensureDaemonWithHandlerRunning -- and runClientWithHandler. These are useful if, for instance, -- you need streaming requests or replies, or if you need to change your -- event handler at runtime. -- -- The event handling loop is provided by runInForeground. You may -- want to use this for debugging purposes or if you want to handle -- daemonization manually. module System.Daemon -- | Simple wrapper around ensureDaemonWithHandlerRunning which uses -- a simple function to respond to commands and doesn't deal with pipes. -- -- The handler is just a function that takes a command and -- returns a response. ensureDaemonRunning :: (Serialize a, Serialize b) => String -> DaemonOptions -> (a -> IO b) -> IO () -- | Start a daemon running on the given port, using the given handler to -- respond to events. If the daemon is already running, don't do -- anything. Returns immediately. -- -- The pidfile PidFile options will be created and locked. This -- function checks the pidfile to see if the daemon is already running. -- -- The daemon will listen for incoming connections on all interfaces on -- daemonPort options. -- -- The handler is a function that takes the reader and writer -- ByteString pipes and does something with them. See -- commandReceiver for an example handler. ensureDaemonWithHandlerRunning :: String -> DaemonOptions -> Handler () -> IO () -- | Send a command to the daemon running at the given network address and -- wait for a response. -- -- This is a simple wrapper around runClientWithHandler that sends -- a single command and waits for a single response. -- -- If the connection is closed before receiving a response, return -- Nothing. runClient :: (Serialize a, Serialize b) => HostName -> Port -> a -> IO (Maybe b) -- | Connect to the given network address and run the handler on the reader -- and wrier pipes for the socket. -- -- The handler is a function that takes the reader and writer -- ByteString pipes and does something with them. For an example -- handler, see commandSender, which sends a command and waits for -- a response. runClientWithHandler :: HostName -> Port -> Handler a -> IO a -- | The configuration options of a daemon. See ensureDaemonRunning -- for a description of each. data DaemonOptions DaemonOptions :: Port -> PidFile -> Bool -> DaemonOptions daemonPort :: DaemonOptions -> Port daemonPidFile :: DaemonOptions -> PidFile printOnDaemonStarted :: DaemonOptions -> Bool -- | The location of the daemon's pidfile. data PidFile InHome :: PidFile PidFile :: FilePath -> PidFile type HostName = String type Port = Int -- | Start the given handler in the foreground. It will listen and respond -- to events on the given port. -- -- This is the function that ensureDaemonWithHandlerRunning runs -- on the daemon thread. runInForeground :: Port -> Handler () -> IO () -- | Create a socket and bind it to the given port. bindPort :: Port -> IO Socket -- | Create a socket connected to the given network address. getSocket :: HostName -> Port -> IO Socket instance Show PidFile instance Show DaemonOptions instance IsString PidFile instance Default DaemonOptions