forked from M-Labs/artiq
dashboard/moninj: use thread instead of asyncio UDP (#39)
This commit is contained in:
parent
1690cb11b3
commit
d9e918be49
|
@ -1,4 +1,5 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import threading
|
||||||
import logging
|
import logging
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
|
@ -273,34 +274,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 loop.create_datagram_endpoint(lambda: self,
|
|
||||||
family=socket.AF_INET)
|
|
||||||
try:
|
|
||||||
await self.subscriber.connect(server, port)
|
await self.subscriber.connect(server, port)
|
||||||
try:
|
try:
|
||||||
TaskObject.start(self)
|
TaskObject.start(self)
|
||||||
except:
|
except:
|
||||||
await self.subscriber.close()
|
await self.subscriber.close()
|
||||||
raise
|
raise
|
||||||
except:
|
|
||||||
self.transport.close()
|
|
||||||
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")
|
||||||
|
@ -330,12 +340,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")
|
||||||
|
@ -344,10 +348,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:
|
||||||
|
|
|
@ -142,7 +142,6 @@ 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)
|
||||||
|
@ -155,10 +154,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)
|
||||||
|
|
Loading…
Reference in New Issue