Make the main thread exit cleanly in case of connection loss.
This commit is contained in:
parent
8551832bd2
commit
50b21c21ee
3 changed files with 26 additions and 9 deletions
|
@ -5,10 +5,12 @@ module Hsbot.Core
|
||||||
|
|
||||||
import Control.Concurrent
|
import Control.Concurrent
|
||||||
import Control.Concurrent.Chan()
|
import Control.Concurrent.Chan()
|
||||||
|
import Control.Exception
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
import Data.List()
|
import Data.List()
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
import Network
|
import Network
|
||||||
|
import Prelude hiding (catch)
|
||||||
import System.IO
|
import System.IO
|
||||||
import System.Time (getClockTime)
|
import System.Time (getClockTime)
|
||||||
|
|
||||||
|
@ -26,9 +28,10 @@ connectServer server = do
|
||||||
handle <- connectTo name $ serverPort server
|
handle <- connectTo name $ serverPort server
|
||||||
hSetBuffering handle NoBuffering
|
hSetBuffering handle NoBuffering
|
||||||
putStrLn "done."
|
putStrLn "done."
|
||||||
putStr $ "Opening server communication channel... "
|
putStr "Opening server communication channel... "
|
||||||
chan <- newChan :: IO (Chan BotMsg)
|
chan <- newChan :: IO (Chan BotMsg)
|
||||||
threadId <- forkIO $ botReader handle chan
|
myFatherThreadId <- myThreadId
|
||||||
|
threadId <- forkIO $ botReader handle chan myFatherThreadId
|
||||||
putStrLn "done."
|
putStrLn "done."
|
||||||
return $ Bot server starttime handle [] M.empty chan threadId M.empty
|
return $ Bot server starttime handle [] M.empty chan threadId M.empty
|
||||||
|
|
||||||
|
@ -36,16 +39,21 @@ connectServer server = do
|
||||||
disconnectServer :: IrcBot ()
|
disconnectServer :: IrcBot ()
|
||||||
disconnectServer = do
|
disconnectServer = do
|
||||||
bot <- get
|
bot <- get
|
||||||
|
let name = serverAddress $ serverConfig bot
|
||||||
|
liftIO $ putStr "Shutting down plugins..."
|
||||||
mapM_ unloadPlugin (M.keys $ botPlugins bot)
|
mapM_ unloadPlugin (M.keys $ botPlugins bot)
|
||||||
|
liftIO $ putStrLn"done."
|
||||||
|
liftIO $ putStr "Closing server communication channel... "
|
||||||
liftIO $ killThread $ readerThreadId bot
|
liftIO $ killThread $ readerThreadId bot
|
||||||
|
liftIO $ putStrLn "done."
|
||||||
|
liftIO $ putStr $ "Disconnecting from " ++ name ++ "... "
|
||||||
liftIO $ hClose $ botHandle bot
|
liftIO $ hClose $ botHandle bot
|
||||||
return ()
|
liftIO $ putStrLn "done."
|
||||||
|
|
||||||
-- | Socket reading loop
|
-- | Socket reading loop
|
||||||
botReader :: Handle -> Chan BotMsg -> IO ()
|
botReader :: Handle -> Chan BotMsg -> ThreadId -> IO ()
|
||||||
botReader handle chan = forever $ do
|
botReader handle chan fatherThreadId = forever $ do
|
||||||
-- TODO : detect end of connection!
|
str <- (hGetLine handle) `catch` handleIOException
|
||||||
str <- hGetLine handle
|
|
||||||
let msg = parseIrcMsg str
|
let msg = parseIrcMsg str
|
||||||
case msg of
|
case msg of
|
||||||
Right msg' -> do
|
Right msg' -> do
|
||||||
|
@ -53,4 +61,11 @@ botReader handle chan = forever $ do
|
||||||
writeChan chan (InputMsg msg')
|
writeChan chan (InputMsg msg')
|
||||||
_ -> do
|
_ -> do
|
||||||
return ()
|
return ()
|
||||||
|
where
|
||||||
|
handleIOException :: IOException -> IO (String)
|
||||||
|
handleIOException ioException = do
|
||||||
|
throwTo fatherThreadId ioException
|
||||||
|
myId <- myThreadId
|
||||||
|
killThread myId
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ imain = do
|
||||||
run :: IrcBot ()
|
run :: IrcBot ()
|
||||||
run = do
|
run = do
|
||||||
initServer
|
initServer
|
||||||
|
liftIO $ putStrLn "Starting plugins..."
|
||||||
loadPlugin "Ping" mainPing
|
loadPlugin "Ping" mainPing
|
||||||
loadPlugin "Core" mainCore
|
loadPlugin "Core" mainCore
|
||||||
loadPlugin "Quote" mainQuote
|
loadPlugin "Quote" mainQuote
|
||||||
|
|
5
TODO
5
TODO
|
@ -1,7 +1,5 @@
|
||||||
:julien!~julien@ogu21.corp PRIVMSG #shbot :@quote graou snif
|
:julien!~julien@ogu21.corp PRIVMSG #shbot :@quote graou snif
|
||||||
|
|
||||||
* Solve the catching that never happen in main
|
|
||||||
* throwto exception to main thread
|
|
||||||
* write a safe reload : try reload before unloading
|
* write a safe reload : try reload before unloading
|
||||||
* discard all trace with a color param and replace those with functions info/warn/error/debug
|
* discard all trace with a color param and replace those with functions info/warn/error/debug
|
||||||
|
|
||||||
|
@ -13,5 +11,8 @@
|
||||||
* add register for casual conversations for plugins?
|
* add register for casual conversations for plugins?
|
||||||
* add a "I have stuff to save so don't kill me too hard" status for plugins
|
* add a "I have stuff to save so don't kill me too hard" status for plugins
|
||||||
|
|
||||||
|
* Handle unix signals properly
|
||||||
|
* Make the bot auto-reconnect (/!\ admin plugin!)
|
||||||
|
|
||||||
* restore \r in IRCParser
|
* restore \r in IRCParser
|
||||||
|
|
||||||
|
|
Reference in a new issue