mirror of
https://github.com/m-labs/artiq.git
synced 2024-12-20 17:06:30 +08:00
Sebastien Bourdeauducq
d5795fd619
Introduces a watchdog context manager to use in the experiment code that terminates the process with an error if it times out. The syntax is: with self.scheduler.watchdog(20*s): ... Watchdogs timers are implemented by the master process (and the worker communicates the necessary information about them) so that they can be enforced even if the worker crashes. They can be nested arbitrarily. During yields, all watchdog timers for the yielding worker are suspended [TODO]. Setting up watchdogs is not supported in kernels, however, a kernel can be called within watchdog contexts (and terminating the worker will terminate the kernel [TODO]). It is possible to implement a heartbeat mechanism using a watchdog, e.g.: for i in range(...): with self.scheduler.watchdog(...): .... Crashes/freezes within the iterator or the loop management would not be detected, but they should be rare enough.
77 lines
2.1 KiB
Python
77 lines
2.1 KiB
Python
from operator import itemgetter
|
|
import importlib.machinery
|
|
import linecache
|
|
import logging
|
|
import sys
|
|
import asyncio
|
|
import time
|
|
import os.path
|
|
|
|
|
|
def format_arguments(arguments):
|
|
fmtargs = []
|
|
for k, v in sorted(arguments.items(), key=itemgetter(0)):
|
|
fmtargs.append(k + "=" + repr(v))
|
|
if fmtargs:
|
|
return ", ".join(fmtargs)
|
|
else:
|
|
return ""
|
|
|
|
|
|
def file_import(filename):
|
|
linecache.checkcache(filename)
|
|
|
|
modname = filename
|
|
i = modname.rfind("/")
|
|
if i > 0:
|
|
modname = modname[i+1:]
|
|
i = modname.find(".")
|
|
if i > 0:
|
|
modname = modname[:i]
|
|
modname = "file_import_" + modname
|
|
|
|
path = os.path.dirname(os.path.realpath(filename))
|
|
sys.path.insert(0, path)
|
|
|
|
loader = importlib.machinery.SourceFileLoader(modname, filename)
|
|
module = loader.load_module()
|
|
|
|
sys.path.remove(path)
|
|
|
|
return module
|
|
|
|
|
|
def verbosity_args(parser):
|
|
group = parser.add_argument_group("verbosity")
|
|
group.add_argument("-v", "--verbose", default=0, action="count",
|
|
help="increase logging level")
|
|
group.add_argument("-q", "--quiet", default=0, action="count",
|
|
help="decrease logging level")
|
|
|
|
|
|
def simple_network_args(parser, default_port):
|
|
group = parser.add_argument_group("network")
|
|
group.add_argument("--bind", default="::1",
|
|
help="hostname or IP address to bind to")
|
|
group.add_argument("-p", "--port", default=default_port, type=int,
|
|
help="TCP port to listen to (default: {})"
|
|
.format(default_port))
|
|
|
|
|
|
def init_logger(args):
|
|
logging.basicConfig(level=logging.WARNING + args.quiet*10 - args.verbose*10)
|
|
|
|
|
|
@asyncio.coroutine
|
|
def asyncio_process_wait_timeout(process, timeout):
|
|
# In Python < 3.5, asyncio.wait_for(process.wait(), ...
|
|
# causes a futures.InvalidStateError inside asyncio if and when the
|
|
# process terminates after the timeout.
|
|
# Work around this problem.
|
|
end_time = time.monotonic() + timeout
|
|
r = True
|
|
while r:
|
|
r = yield from asyncio.wait_for(
|
|
process.stdout.read(1024),
|
|
timeout=end_time - time.monotonic())
|