Fix run cleanup if the UI ends without clearing non-Hooke msgs from the Queue.
authorW. Trevor King <wking@drexel.edu>
Tue, 3 Aug 2010 15:03:45 +0000 (11:03 -0400)
committerW. Trevor King <wking@drexel.edu>
Tue, 3 Aug 2010 15:03:45 +0000 (11:03 -0400)
If the UI closes before the last command finishes (e.g. if bin/hooke
is run in a pipe), there may be cruft (e.g. CommandExit instances)
left in the engine-to-UI queue before the Hooke instance that the
CommandEngine appends on closing.  The new implementation keeps
digging through the queue until it finds a Hooke instance, where the
old implementation only looked at the first message that came off the
queue.

Also added some useful debugging logs for UI<->Engine communication.

hooke/engine.py
hooke/hooke.py

index b91551c2985ecd44528b292b27f7cb057dd00560..ca4461d9bc6800de936b6f740d667ca02c7c969a 100644 (file)
 :class:`hooke.command.Command`\s.
 """
 
 :class:`hooke.command.Command`\s.
 """
 
+import logging
+
 from .ui import CloseEngine, CommandMessage
 
 from .ui import CloseEngine, CommandMessage
 
+
 class CommandEngine (object):
     def run(self, hooke, ui_to_command_queue, command_to_ui_queue):
         """Get a :class:`hooke.ui.QueueMessage` from the incoming
 class CommandEngine (object):
     def run(self, hooke, ui_to_command_queue, command_to_ui_queue):
         """Get a :class:`hooke.ui.QueueMessage` from the incoming
@@ -37,11 +40,16 @@ class CommandEngine (object):
         `command_to_ui_queue`, at which point the `CommandEngine` will
         be ready to receive the next :class:`hooke.ui.QueueMessage`.
         """
         `command_to_ui_queue`, at which point the `CommandEngine` will
         be ready to receive the next :class:`hooke.ui.QueueMessage`.
         """
+        log = logging.getLogger('hooke')
         while True:
         while True:
+            log.debug('engine waiting for command')
             msg = ui_to_command_queue.get()
             if isinstance(msg, CloseEngine):
                 command_to_ui_queue.put(hooke)
             msg = ui_to_command_queue.get()
             if isinstance(msg, CloseEngine):
                 command_to_ui_queue.put(hooke)
+                log.debug(
+                    'engine closing, placed hooke instance in return queue')
                 break
             assert isinstance(msg, CommandMessage), type(msg)
                 break
             assert isinstance(msg, CommandMessage), type(msg)
+            log.debug('engine running %s' % msg.command.name)
             msg.command.run(hooke, ui_to_command_queue, command_to_ui_queue,
                             **msg.arguments)
             msg.command.run(hooke, ui_to_command_queue, command_to_ui_queue,
                             **msg.arguments)
index 1923d229c6151bdc241c51f6e4df99dcd047e43d..c2ef159d8bccc4bbbfe5ac5b789ad52ae55132f1 100644 (file)
@@ -59,6 +59,7 @@ import logging.config
 import multiprocessing
 import optparse
 import os.path
 import multiprocessing
 import optparse
 import os.path
+import Queue
 import unittest
 import StringIO
 import sys
 import unittest
 import StringIO
 import sys
@@ -156,9 +157,14 @@ class HookeRunner (object):
         return (ui_to_command, command_to_ui, command)
 
     def _cleanup_run(self, ui_to_command, command_to_ui, command):
         return (ui_to_command, command_to_ui, command)
 
     def _cleanup_run(self, ui_to_command, command_to_ui, command):
+        log = logging.getLogger('hooke')
+        log.debug('cleanup sending CloseEngine')
         ui_to_command.put(ui.CloseEngine())
         ui_to_command.put(ui.CloseEngine())
-        hooke = command_to_ui.get()
-        assert isinstance(hooke, Hooke)
+        hooke = None
+        while not isinstance(hooke, Hooke):
+            log.debug('cleanup waiting for Hooke instance from the engine.')
+            hooke = command_to_ui.get(block=True)
+            log.debug('cleanup got %s instance' % type(hooke))
         command.join()
         return hooke
 
         command.join()
         return hooke