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