dashboard/moninj: use thread instead of asyncio UDP (#39)

This commit is contained in:
Sebastien Bourdeauducq 2016-04-11 18:09:41 +08:00
parent 2617b9db82
commit e4833a33fc
2 changed files with 36 additions and 34 deletions

View File

@ -141,10 +141,9 @@ def main():
atexit_register_coroutine(d_applets.stop) atexit_register_coroutine(d_applets.stop)
smgr.register(d_applets) smgr.register(d_applets)
if os.name != "nt": d_ttl_dds = moninj.MonInj()
d_ttl_dds = moninj.MonInj() loop.run_until_complete(d_ttl_dds.start(args.server, args.port_notify))
loop.run_until_complete(d_ttl_dds.start(args.server, args.port_notify)) atexit_register_coroutine(d_ttl_dds.stop)
atexit_register_coroutine(d_ttl_dds.stop)
d_schedule = schedule.ScheduleDock( d_schedule = schedule.ScheduleDock(
status_bar, rpc_clients["schedule"], sub_clients["schedule"]) status_bar, rpc_clients["schedule"], sub_clients["schedule"])
@ -154,10 +153,11 @@ def main():
smgr.register(logmgr) smgr.register(logmgr)
# lay out docks # lay out docks
right_docks = [d_explorer, d_shortcuts] right_docks = [
if os.name != "nt": d_explorer, d_shortcuts,
right_docks += [d_ttl_dds.ttl_dock, d_ttl_dds.dds_dock] d_ttl_dds.ttl_dock, d_ttl_dds.dds_dock,
right_docks += [d_datasets, d_applets] d_datasets, d_applets
]
main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, right_docks[0]) main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, right_docks[0])
for d1, d2 in zip(right_docks, right_docks[1:]): for d1, d2 in zip(right_docks, right_docks[1:]):
main_window.tabifyDockWidget(d1, d2) main_window.tabifyDockWidget(d1, d2)

View File

@ -1,4 +1,5 @@
import asyncio import asyncio
import threading
import logging import logging
import socket import socket
import struct import struct
@ -261,34 +262,43 @@ class MonInj(TaskObject):
self.subscriber = Subscriber("devices", self.init_devices) self.subscriber = Subscriber("devices", self.init_devices)
self.dm = None self.dm = None
self.transport = None self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Never ceasing to disappoint, asyncio has an issue about UDP
# not being supported on Windows (ProactorEventLoop) open since 2014.
self.loop = asyncio.get_event_loop()
self.thread = threading.Thread(target=self.receiver_thread,
daemon=True)
self.thread.start()
async def start(self, server, port): async def start(self, server, port):
loop = asyncio.get_event_loop() await self.subscriber.connect(server, port)
await loop.create_datagram_endpoint(lambda: self,
family=socket.AF_INET)
try: try:
await self.subscriber.connect(server, port) TaskObject.start(self)
try:
TaskObject.start(self)
except:
await self.subscriber.close()
raise
except: except:
self.transport.close() await self.subscriber.close()
raise raise
async def stop(self): async def stop(self):
await TaskObject.stop(self) await TaskObject.stop(self)
await self.subscriber.close() await self.subscriber.close()
if self.transport is not None: try:
self.transport.close() # This is required to make recvfrom terminate in the thread.
self.transport = None # On Linux, this raises "OSError: Transport endpoint is not
# connected", but still has the intended effect.
self.socket.shutdown(socket.SHUT_RDWR)
except OSError:
pass
self.socket.close()
self.thread.join()
def connection_made(self, transport): def receiver_thread(self):
self.transport = transport while True:
data, addr = self.socket.recvfrom(2048)
if addr is None:
break
self.loop.call_soon_threadsafe(self.datagram_received, data)
def datagram_received(self, data, addr): def datagram_received(self, data):
if self.dm is None: if self.dm is None:
logger.debug("received datagram, but device manager " logger.debug("received datagram, but device manager "
"is not present yet") "is not present yet")
@ -318,12 +328,6 @@ class MonInj(TaskObject):
except: except:
logger.warning("failed to process datagram", exc_info=True) logger.warning("failed to process datagram", exc_info=True)
def error_received(self, exc):
logger.warning("datagram endpoint error")
def connection_lost(self, exc):
self.transport = None
def send_to_device(self, data): def send_to_device(self, data):
if self.dm is None: if self.dm is None:
logger.debug("cannot sent to device yet, no device manager") logger.debug("cannot sent to device yet, no device manager")
@ -332,10 +336,8 @@ class MonInj(TaskObject):
logger.debug("core device address: %s", ca) logger.debug("core device address: %s", ca)
if ca is None: if ca is None:
logger.warning("could not find core device address") logger.warning("could not find core device address")
elif self.transport is None:
logger.warning("datagram endpoint not available")
else: else:
self.transport.sendto(data, (ca, 3250)) self.socket.sendto(data, (ca, 3250))
async def _do(self): async def _do(self):
while True: while True: