31
31
# -----------------------------------------------------------------------------
42
# kaa.notifier imports
43
import nf_wrapper as notifier
48
from callback import *
53
from yieldfunc import *
54
from jobserver import ThreadCallback, execute_in_thread
55
from jobserver import killall as kill_jobserver
56
from async import InProgress
58
from decorators import execute_in_timer, execute_in_mainloop
61
log = logging.getLogger('notifier')
63
# variable to check if the notifier is running
65
# Set if currently in shutdown() (to prevent reentrancy)
68
def _step_signal_changed(signal, flag):
69
if flag == Signal.SIGNAL_CONNECTED and signal.count() == 1:
70
notifier.dispatcher_add(signals["step"].emit)
71
elif flag == Signal.SIGNAL_DISCONNECTED and signal.count() == 0:
72
notifier.dispatcher_remove(signals["step"].emit)
77
"step": Signal(changed_cb = _step_signal_changed),
83
Shutdown notifier and kill all background processes.
87
# Ensure shutdown() is called from main thread.
88
if not is_mainthread():
89
return MainThreadCallback(shutdown)()
92
# notifier loop still running, send system exit
93
log.info('Stop notifier loop')
101
signals["shutdown"].emit()
102
signals["shutdown"].disconnect_all()
103
signals["step"].disconnect_all()
105
# Kill processes _after_ shutdown emits to give callbacks a chance to
106
# close them properly.
109
# Collect any zombies
111
os.waitpid(-1, os.WNOHANG)
118
Notifier main loop function. It will loop until an exception
119
is raised or sys.exit is called.
124
set_current_as_mainthread()
127
except (KeyboardInterrupt, SystemExit):
129
# This looks stupid, I know that. The problem is that if we have
130
# a KeyboardInterrupt, that flag is still valid somewhere inside
131
# python. The next system call will fail because of that. Since we
132
# don't want a join of threads or similar fail, we use a very short
133
# sleep here. In most cases we won't sleep at all because this sleep
134
# fails. But after that everything is back to normal.
139
log.exception('loop')
144
def step(*args, **kwargs):
146
Notifier step function with signal support.
148
if not is_mainthread():
149
# If step is being called from a thread, wake up the mainthread
150
# instead of allowing the thread into notifier.step.
152
# Sleep for epsilon to prevent busy loops.
157
notifier.step(*args, **kwargs)
158
except (KeyboardInterrupt, SystemExit):
162
def _shutdown_check(*args):
163
# Helper function to shutdown kaa on system exit
164
# The problem is that pytgtk just exits python and
165
# does not simply return from the main loop and kaa
166
# can't call the shutdown handler. This is not a perfect
167
# solution, e.g. with the generic notifier you can do
168
# stuff after kaa.main() which is not possible with gtk
171
# If the kaa mainthread (i.e. thread the mainloop is running in)
172
# is not the program's main thread, then is_mainthread() will be False
173
# and we don't need to set running=False since shutdown() will raise a
174
# SystemExit and things will exit normally.
179
# # catch SIGTERM if possible for a clean shutdown
180
if threading.enumerate()[0] == threading.currentThread():
181
signal.signal(signal.SIGTERM, _shutdown_check)
183
log.info('kaa imported from thread, disable SIGTERM handler')
185
# check to make sure we really call our shutdown function
186
atexit.register(_shutdown_check)
33
# Import all classes, functions and decorators that are part of the API
36
from callback import Callback, WeakCallback
38
# Signal and dict of Signals
39
from signals import Signal, Signals
42
from async import TimeoutException, InProgress, InProgressCallback, InProgressSignals
44
# Thread callbacks, helper functions and decorators
45
from thread import MainThreadCallback, NamedThreadCallback, ThreadCallback, \
46
is_mainthread, threaded, MAINTHREAD, synchronized
48
# Timer classes and decorators
49
from timer import Timer, WeakTimer, OneShotTimer, WeakOneShotTimer, AtTimer, \
50
OneShotAtTimer, timed, POLICY_ONCE, POLICY_MANY, POLICY_RESTART
53
from sockets import IOMonitor, WeakIOMonitor, Socket, IO_READ, IO_WRITE
55
# Event and event handler classes
56
from event import Event, EventHandler, WeakEventHandler
58
# coroutine decorator and helper classes
59
from coroutine import NotFinished, coroutine
62
from popen import Process
64
# special gobject thread support
65
from gobject import GOBJECT, gobject_set_threaded