changeset 18:69efb6cdc127

Added some error-handling code, though the channel code is raising exceptions in it at the moment I think.
author Atul Varma <varmaa@toolness.com>
date Sun, 19 Apr 2009 21:45:46 -0700
parents 7b652e2ac62e
children 264e243e396c
files cosocket.py
diffstat 1 files changed, 37 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/cosocket.py	Sun Apr 19 20:29:17 2009 -0700
+++ b/cosocket.py	Sun Apr 19 21:45:46 2009 -0700
@@ -5,6 +5,7 @@
 import asyncore
 import asynchat
 import types
+import traceback
 
 class _AsyncChatCoroutineDispatcher(asynchat.async_chat):
     def __init__(self, coroutine, conn = None):
@@ -16,15 +17,25 @@
         if conn:
             self.return_from_yield()
 
-    def return_from_yield(self, message = None):
+    def return_from_yield(self, message = None, exception = None):
         try:
-            instruction = self.__coroutine.send(message)
+            if exception:
+                instruction = self.__coroutine.throw(exception)
+            else:
+                instruction = self.__coroutine.send(message)
         except StopIteration:
             if self.__coroutine_stack:
                 self.__coroutine = self.__coroutine_stack.pop()
                 self.return_from_yield()
             else:
-                self.close()
+                self.__coroutine = None
+                self.handle_close()
+        except Exception, e:
+            if self.__coroutine_stack:
+                self.__coroutine = self.__coroutine_stack.pop()
+                self.return_from_yield(exception = e)
+            else:
+                self.handle_error()
         else:
             if type(instruction) == types.GeneratorType:
                 self.__coroutine_stack.append(self.__coroutine)
@@ -33,6 +44,29 @@
             else:
                 instruction.execute(self)
 
+    def __close_coroutine(self, coroutine):
+        try:
+            coroutine.close()
+        except Exception:
+            self.log_info(traceback.format_exc(), 'error')
+
+    def handle_close(self):
+        if self.__coroutine:
+            # Pass an exception back into the coroutine to kick
+            # it out of whatever yielding state it's in.
+            self.__close_coroutine(self.__coroutine)
+            self.__coroutine = None
+            while self.__coroutine_stack:
+                self.__close_coroutine(self.__coroutine_stack.pop())
+        self.close()
+
+    def log_info(self, message, type='info'):
+        # TODO: Use the logging module here.
+        print '%s: %s' % (type, message)
+
+    def handle_error(self):
+        self.log_info(traceback.format_exc(), 'error')
+
     def handle_connect(self):
         self.return_from_yield()