+ -- The rest of the program is kicked off by the following line which
+ -- begins connecting to our feed hosts, starting with the first one,
+ -- and proceeds in a round-robin fashion.
+ let run_program = round_robin cfg 0
+
+ -- If we were asked to daemonize, do that; otherwise just run the thing.
+ if (daemonize cfg)
+ then try_daemonize cfg run_program
+ else run_program
+
+ where
+ -- | This is the top-level \"loop forever\" function. If an
+ -- exception is thrown, it will propagate up to this point, where
+ -- it will be logged and ignored in style.
+ --
+ -- Afterwards, we recurse (call ourself) again to loop more forevers.
+ --
+ round_robin :: Configuration -> Int -> IO ()
+ round_robin cfg feed_host_idx = do
+ let hosts = get_feed_hosts $ feed_hosts cfg
+ let host = hosts !! feed_host_idx
+ catchIOError (connect_and_parse cfg host) (report_error . show)
+ thread_sleep 5 -- Wait 5s before attempting to reconnect.
+ round_robin cfg $ (feed_host_idx + 1) `mod` (length hosts)
+
+
+ -- | A exception handler around full_daemonize. If full_daemonize
+ -- doesn't work, we report the error and crash. This is fine; we
+ -- only need the program to be resilient once it actually starts.
+ --
+ try_daemonize :: Configuration -> IO () -> IO ()
+ try_daemonize cfg program =
+ catchIOError
+ (full_daemonize cfg program)
+ (\e -> do
+ report_error (show e)
+ throw e)