changeset 2659:892055d122fb

Handle process/thread termination gracefully.
author Karol 'grzywacz' Nowak <grzywacz@sul.uni.lodz.pl>
date Wed, 08 Aug 2007 20:09:41 +0200
parents 459199b59cf7
children 9a17fabb8008 9f6e830c82e0
files jabberbot/main.py jabberbot/xmlrpcbot.py jabberbot/xmppbot.py
diffstat 3 files changed, 59 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/jabberbot/main.py	Wed Aug 08 00:47:13 2007 +0200
+++ b/jabberbot/main.py	Wed Aug 08 20:09:41 2007 +0200
@@ -6,7 +6,7 @@
     @license: GNU GPL, see COPYING for details.
 """
 
-import logging, os, sys
+import logging, os, sys, time
 from Queue import Queue
 
 from jabberbot.config import BotConfig
@@ -36,18 +36,43 @@
     commands_from_xmpp = Queue()
     commands_to_xmpp = Queue()
 
-    try:
-        xmpp_bot = XMPPBot(BotConfig, commands_from_xmpp, commands_to_xmpp)
-        xmlrpc_client = XMLRPCClient(BotConfig, commands_from_xmpp, commands_to_xmpp)
-        xmlrpc_server = XMLRPCServer(BotConfig, commands_to_xmpp)
+    xmpp_bot = None
+    xmlrpc_client = None
+    xmlrpc_server = None
 
-        xmpp_bot.start()
-        xmlrpc_client.start()
-        xmlrpc_server.start()
+    while True:
+        try:
+            if not xmpp_bot or not xmpp_bot.isAlive():
+                log.info("(Re)starting XMPP thread...")
+                xmpp_bot = XMPPBot(BotConfig, commands_from_xmpp, commands_to_xmpp)
+                xmpp_bot.setDaemon(True)
+                xmpp_bot.start()
 
-    except KeyboardInterrupt, i:
-        print i
-        sys.exit(0)
+            if not xmlrpc_client or not xmlrpc_client.isAlive():
+                log.info("(Re)starting XMLRPC client thread...")
+                xmlrpc_client = XMLRPCClient(BotConfig, commands_from_xmpp, commands_to_xmpp)
+                xmlrpc_client.setDaemon(True)
+                xmlrpc_client.start()
+
+            if not xmlrpc_server or not xmlrpc_server.isAlive():
+                log.info("(Re)starting XMLRPC server thread...")
+                xmlrpc_server = XMLRPCServer(BotConfig, commands_to_xmpp)
+                xmlrpc_server.setDaemon(True)
+                xmlrpc_server.start()
+
+            time.sleep(5)
+
+        except KeyboardInterrupt, i:
+            print i
+            xmpp_bot.stop()
+            xmlrpc_client.stop()
+
+            log.info("Stopping XMPP bot thread, please wait...")
+            xmpp_bot.join(5)
+            log.info("Stopping XMLRPC client thread, please wait...")
+            xmlrpc_client.join(5)
+
+            sys.exit(0)
 
 
 if __name__ == "__main__":
--- a/jabberbot/xmlrpcbot.py	Wed Aug 08 00:47:13 2007 +0200
+++ b/jabberbot/xmlrpcbot.py	Wed Aug 08 20:09:41 2007 +0200
@@ -93,16 +93,24 @@
         self.connection = self.create_connection()
         self.token = None
         self.multicall = None
+        self.stopping = False
 
     def run(self):
         """Starts the server / thread"""
         while True:
+            if self.stopping:
+                break
+
             try:
                 command = self.commands_in.get(True, 2)
                 self.execute_command(command)
             except Queue.Empty:
                 pass
 
+    def stop(self):
+        """Stop the thread"""
+        self.stopping = True
+
     def create_connection(self):
         return xmlrpclib.ServerProxy(self.url, allow_none=True, verbose=self.config.verbose)
 
@@ -158,10 +166,10 @@
 
     def _get_multicall_result(self, jid):
         """Returns multicall results and issues a warning if there's an auth error
-        
+
         @param jid: a full JID to use if there's an error
         @type jid: str
-        
+
         """
 
         if not self.token:
--- a/jabberbot/xmppbot.py	Wed Aug 08 00:47:13 2007 +0200
+++ b/jabberbot/xmppbot.py	Wed Aug 08 20:09:41 2007 +0200
@@ -162,6 +162,7 @@
 
         # How often should the contacts be checked for expiration, in seconds
         self.contact_check = 600
+        self.stopping = False
 
         self.known_xmlrpc_cmds = [cmd.GetPage, cmd.GetPageHTML, cmd.GetPageList, cmd.GetPageInfo, cmd.Search]
         self.internal_commands = ["ping", "help", "searchform"]
@@ -179,10 +180,17 @@
         self.connect()
         self.loop()
 
+    def stop(self):
+        """Stop the thread"""
+        self.stopping = True
+
     def loop(self, timeout=1):
         """Main event loop - stream and command handling"""
 
         while True:
+            if self.stopping:
+                break
+
             stream = self.get_stream()
             if not stream:
                 break
@@ -407,14 +415,14 @@
                 use_oob = True
             else:
                 url_strings = ['%s - %s' % (entry['url'], entry['description']) for entry in data['url_list']]
-                
+
                 # Insert a newline, so that the list of URLs doesn't start in the same
                 # line as the rest of message text
                 url_strings.insert(0, '\n')
                 data['text'] = data['text'] + '\n'.join(url_strings)
-                    
+
         message = Message(to_jid=jid, body=data['text'], stanza_type=msg_type, subject=subject)
-        
+
         if use_oob:
             oob.add_urls(message, data['url_list'])
 
@@ -739,12 +747,12 @@
         @param stanza: a received result stanza
         """
         payload = stanza.get_query()
-        
+
         supports = payload.xpathEval('//*[@var="jabber:x:data"]')
         if supports:
             jid = stanza.get_from_jid()
             self.contacts[jid.bare().as_utf8()].set_supports(jid.resource, u"jabber:x:data")
-            
+
         supports = payload.xpathEval('//*[@var="jabber:x:oob"]')
         if supports:
             jid = stanza.get_from_jid()