Author: dmeyer
Date: Thu Feb 21 05:21:38 2008
New Revision: 3122

Log:
Fix notifier shutdown when the kaa mainloop is running besides
another mainloop (e.g. twisted). There is now a nf_wrapper shutdown
function to replace the normal sys.exit with something backend
specific.


Modified:
   trunk/base/src/notifier/main.py
   trunk/base/src/notifier/nf_thread.py
   trunk/base/src/notifier/nf_wrapper.py
   trunk/base/src/notifier/reactor.py
   trunk/base/test/kaa_in_twisted.py
   trunk/base/test/twisted_in_kaa.py

Modified: trunk/base/src/notifier/main.py
==============================================================================
--- trunk/base/src/notifier/main.py     (original)
+++ trunk/base/src/notifier/main.py     Thu Feb 21 05:21:38 2008
@@ -161,13 +161,13 @@
     """
     global _shutting_down
 
+    if _shutting_down:
+        return
+
     if is_running():
         # notifier loop still running, send system exit
         log.info('Stop notifier loop')
-        raise SystemExit
-
-    if _shutting_down:
-        return
+        notifier.shutdown()
 
     _shutting_down = True
 
@@ -253,7 +253,9 @@
 # catch SIGTERM and SIGINT if possible for a clean shutdown
 if threading.enumerate()[0] == threading.currentThread():
     def signal_handler(*args):
-        sys.exit(0)
+        # use the preferred stop function for the notifier. Most notifier
+        # backends only call sys.exit(0). Some, like twisted need specific 
code.
+        notifier.shutdown()
     signal.signal(signal.SIGTERM, signal_handler)
     signal.signal(signal.SIGINT, signal_handler)
 else:

Modified: trunk/base/src/notifier/nf_thread.py
==============================================================================
--- trunk/base/src/notifier/nf_thread.py        (original)
+++ trunk/base/src/notifier/nf_thread.py        Thu Feb 21 05:21:38 2008
@@ -37,7 +37,7 @@
 
 # kaa.notifier imports
 import kaa
-import nf_wrapper
+import nf_wrapper as notifier
 from main import _set_running as set_mainloop_running
 
 # get logging object
@@ -49,10 +49,10 @@
     """
     def __init__(self, interleave, shutdown = None):
         super(ThreadLoop, self).__init__()
+        if shutdown is not None:
+            # special shutdown function
+            notifier.shutdown = shutdown
         self._call_mainloop = interleave
-        self._mainloop_shutdown = kaa.main.stop
-        if shutdown:
-            self._mainloop_shutdown = shutdown
         self._lock = threading.Semaphore(0)
         self.sleeping = False
 
@@ -63,10 +63,10 @@
         """
         try:
             try:
-                nf_wrapper.step(sleep = False)
+                notifier.step(sleep = False)
             except (KeyboardInterrupt, SystemExit):
                 set_mainloop_running(False)
-                self._mainloop_shutdown()
+                notifier.shutdown()
         finally:
             self._lock.release()
 
@@ -79,7 +79,7 @@
         try:
             while True:
                 self.sleeping = True
-                nf_wrapper.step(simulate = True)
+                notifier.step(simulate = True)
                 self.sleeping = False
                 if not kaa.main.is_running():
                     break
@@ -96,7 +96,7 @@
             # should never happen because we call no callbacks.
             log.warning('thread loop stopped')
             set_mainloop_running(False)
-            self._call_mainloop(self._mainloop_shutdown)
+            self._call_mainloop(self.notifier.shutdown)
 
 
     def stop(self):
@@ -147,13 +147,17 @@
         loop = ThreadLoop(handler, shutdown)
     else:
         raise RuntimeError('unknown notifier module %s', module)
-    nf_wrapper.init( 'generic', force_internal=True, **options )
+    notifier.init( 'generic', force_internal=True, **options )
+    if shutdown is not None:
+        # set specific shutdown function
+        notifier.shutdown = shutdown
     # set main thread and init thread pipe
     kaa.main.set_as_mainthread()
     # adding a timer or socket is not thread safe in general but
     # an additional wakeup we don't need does not hurt. And in
     # simulation mode the step function does not modify the
     # internal variables.
-    nf_wrapper.timer_add = Wakeup(loop, nf_wrapper.timer_add)
-    nf_wrapper.socket_add = Wakeup(loop, nf_wrapper.socket_add)
+    notifier.timer_add = Wakeup(loop, notifier.timer_add)
+    notifier.socket_add = Wakeup(loop, notifier.socket_add)
     loop.start()
+    return loop

Modified: trunk/base/src/notifier/nf_wrapper.py
==============================================================================
--- trunk/base/src/notifier/nf_wrapper.py       (original)
+++ trunk/base/src/notifier/nf_wrapper.py       Thu Feb 21 05:21:38 2008
@@ -126,6 +126,9 @@
 socket_remove = _Wrapper('socket_remove')
 socket_add = _Wrapper('socket_add')
 
+def shutdown():
+    # prefered way to shut down the system
+    sys.exit(0)
 
 # socket wrapper
 
@@ -149,6 +152,7 @@
     global nf_socket_remove
     global nf_socket_add
     global nf_conditions
+    global shutdown
 
     if not isinstance(timer_add, _Wrapper):
         raise RuntimeError('notifier already initialized')
@@ -156,7 +160,7 @@
     if not 'recursive_depth' in options:
         # default value of 2 is not enough when using async yield stuff
         options['recursive_depth'] = 5
-        
+
     try:
         if force_internal:
             # pynotifier is not allowed
@@ -204,6 +208,11 @@
 
     step = notifier.step
 
+    if module == 'twisted':
+        # special stop handling for twisted
+        from twisted.internet import reactor
+        shutdown = reactor.stop
+
 
 def _shutdown_weakref_destroyed():
     global _python_shutting_down

Modified: trunk/base/src/notifier/reactor.py
==============================================================================
--- trunk/base/src/notifier/reactor.py  (original)
+++ trunk/base/src/notifier/reactor.py  Thu Feb 21 05:21:38 2008
@@ -73,6 +73,15 @@
         kaa.main.run()
 
 
+    def stop(self):
+        """
+        Stop the reactor by stopping both the kaa main loop and the
+        twisted reactor part.
+        """
+        kaa.main.stop()
+        super(KaaReactor,self).stop()
+
+
 def install():
     """
     Configure the twisted mainloop to be run using the kaa reactor.

Modified: trunk/base/test/kaa_in_twisted.py
==============================================================================
--- trunk/base/test/kaa_in_twisted.py   (original)
+++ trunk/base/test/kaa_in_twisted.py   Thu Feb 21 05:21:38 2008
@@ -1,6 +1,18 @@
 import sys
 import kaa
 
+# method can be either
+# 0: use thread based notifier
+# 1: use twisted thread based notifier
+# 2: use twisted experimental pynotifier
+#    Known Bug: Twisted does not stop the reactor on SystemExit. If a
+#    callback calls sys.exit() to shutdown the program, this won't work.
+#    This has to be fixed in pynotifier
+method = 2
+
+# test auto-stop or stop with C-c
+stop_on_exit = True
+
 # get reactor
 from twisted.internet import reactor
 
@@ -9,25 +21,44 @@
     
 def twisted_callback2():
     print "twisted (shutdown)", kaa.is_mainthread()
-    reactor.stop()
+    if not stop_on_exit:
+        return
+    if method == 2:
+        kaa.main.stop()
+    else:
+        reactor.stop()
     
 def kaa_callback():
     print 'kaa', kaa.is_mainthread()
-    # sys.exit(0)
 
 def shutdown_callback():
     print 'shutdown signal'
-    
-kaa.main.select_notifier('thread', handler = reactor.callFromThread, \
-                         shutdown = reactor.stop)
-# there is special code in kaa that does the same by calling
-# kaa.main.select_notifier('twisted')
 
-reactor.callLater(2.5, twisted_callback1)
-reactor.callLater(3.5, twisted_callback2)
+if method == 0:
+    # select the thread loop and provide callbacks for a hander and how to
+    # stop the real mainloop
+    loop = kaa.main.select_notifier('thread', handler = 
reactor.callFromThread, \
+                                    shutdown = reactor.stop)
+    # stop the thread when twisted is done. Without this code the app will wait
+    # until the nf thread will be done which will never happen.
+    reactor.addSystemEventTrigger('after', 'shutdown', loop.stop)
+
+if method == 1:
+    # there is special code in kaa that does the same as method 0
+    kaa.main.select_notifier('twisted')
+if method == 2:
+    # or use the real twisted notifier
+    kaa.main.select_notifier('twisted_experimental')
+
+reactor.callLater(0.5, twisted_callback1)
+reactor.callLater(1.5, twisted_callback2)
 kaa.Timer(kaa_callback).start(1)
 kaa.main.signals['shutdown'].connect(shutdown_callback)
 
-reactor.run()
+if method == 2:
+    # the twisted_experimental needs kaa.main.run()
+    kaa.main.run()
+else:
+    reactor.run()
 
 print 'done'

Modified: trunk/base/test/twisted_in_kaa.py
==============================================================================
--- trunk/base/test/twisted_in_kaa.py   (original)
+++ trunk/base/test/twisted_in_kaa.py   Thu Feb 21 05:21:38 2008
@@ -19,8 +19,8 @@
     print 'kaa', kaa.is_mainthread()
     # sys.exit(0)
     
-reactor.callLater(2.5, twisted_callback1)
-reactor.callLater(3.5, twisted_callback2)
+reactor.callLater(0.5, twisted_callback1)
+reactor.callLater(1.5, twisted_callback2)
 kaa.Timer(kaa_callback).start(1)
 
 # you can either call notifier.main() or reactor.run()

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to