changeset 93:3be28af79baf

Fixed a really bad bug in timeout detection.
author Atul Varma <varmaa@toolness.com>
date Fri, 01 May 2009 18:53:07 -0700
parents 1414765e0929
children abb3952c2209
files cosocket.py media/js/openwebchat.js
diffstat 2 files changed, 25 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/cosocket.py	Sat May 02 01:04:30 2009 +0000
+++ b/cosocket.py	Fri May 01 18:53:07 2009 -0700
@@ -8,12 +8,13 @@
 import weakref
 import logging
 
+DEFAULT_LOOP_TIMEOUT = 1.0
 DEFAULT_TIMEOUT = 90.0
 DEFAULT_MAX_DATA = 65536
 
 time_map = {}
 
-def loop(timeout = DEFAULT_TIMEOUT):
+def loop(timeout = DEFAULT_LOOP_TIMEOUT):
     start_time = time.time()
     while 1:
         asyncore.loop(timeout = timeout, count = 1)
@@ -21,8 +22,18 @@
         time_elapsed = curr_time - start_time
         if time_elapsed > timeout:
             start_time = curr_time
-            for func in time_map.values():
-                func(time_elapsed)
+            funcs_to_call = []
+            for func in time_map:
+                time_map[func] -= time_elapsed
+                if time_map[func] <= 0:
+                    funcs_to_call.append(func)
+            for func in funcs_to_call:
+                del time_map[func]
+            for func in funcs_to_call:
+                try:
+                    func()
+                except:
+                    logging.error(traceback.format_exc())
 
 class _AsyncChatCoroutineDispatcher(asynchat.async_chat):
     def __init__(self, coroutine, conn = None):
@@ -30,11 +41,10 @@
         self.set_terminator(None)
         self.__max_data = DEFAULT_MAX_DATA
         self.__coroutine = coroutine
+        self.__timeout = 0
         self.__data = []
         self.__data_len = 0
         self.__coroutine_stack = []
-        self.__timeout = 0
-        self.__time_passed = 0
         if conn:
             self.continue_from_yield()
 
@@ -128,23 +138,19 @@
             self.connected):
             self.continue_from_yield()
 
-    def __on_tick(self, time_elapsed):
-        self.__time_passed += time_elapsed
-        if self.__time_passed > self.__timeout:
-            self.log_info("Timeout expired (%ss)." % self.__timeout,
-                          'error')
-            self.handle_close()
+    def __on_timeout(self):
+        self.log_info("Timeout expired (%ss)." % self.__timeout,
+                      'error')
+        self.handle_close()
 
     def clear_timeout(self):
         self.__timeout = 0
-        self.__time_passed = 0
-        if self.__on_tick in time_map:
-            del time_map[self.__on_tick]
+        if self.__on_timeout in time_map:
+            del time_map[self.__on_timeout]
 
     def set_timeout(self, timeout):
         self.__timeout = timeout
-        self.__time_passed = 0
-        time_map[self.__on_tick] = self.__on_tick
+        time_map[self.__on_timeout] = timeout
 
     def collect_incoming_data(self, data):
         self.__data.append(data)
@@ -174,7 +180,7 @@
         self.bind(addr)
         self.listen(1)
 
-    def run(self, timeout = DEFAULT_TIMEOUT):
+    def run(self, timeout = DEFAULT_LOOP_TIMEOUT):
         loop(timeout)
 
     def handle_accept(self):
--- a/media/js/openwebchat.js	Sat May 02 01:04:30 2009 +0000
+++ b/media/js/openwebchat.js	Fri May 01 18:53:07 2009 -0700
@@ -90,10 +90,8 @@
        dataType: 'json',
        timeout: self.LISTEN_TIMEOUT,
        error: function(xhr, textStatus, errorThrown) {
-           if (textStatus == "timeout" ||
-               textStatus == "parsererror")
-           // Start another long poll ('parsererror' just means
-           // our content length was 0, which isn't valid JSON).
+         if (textStatus == "timeout")
+           // Start another long poll.
            self.listenForMessages(options);
          else
            options.onError([textStatus, errorThrown]);