forked from M-Labs/artiq
worker: wait for process termination
This prevents stray SIGCHLDs from crashing the program e.g. if the asyncio event loop is closed before the process actually terminates.
This commit is contained in:
parent
c843c353d7
commit
a6a476593e
|
@ -7,7 +7,8 @@ import time
|
||||||
|
|
||||||
from artiq.protocols import pyon
|
from artiq.protocols import pyon
|
||||||
from artiq.language.units import strip_unit
|
from artiq.language.units import strip_unit
|
||||||
from artiq.tools import asyncio_process_wait_timeout, asyncio_wait_or_cancel
|
from artiq.tools import (asyncio_process_wait_timeout, asyncio_process_wait,
|
||||||
|
asyncio_wait_or_cancel)
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -101,6 +102,7 @@ class Worker:
|
||||||
logger.warning("failed to send terminate command to worker"
|
logger.warning("failed to send terminate command to worker"
|
||||||
" (RID %d), killing", self.rid, exc_info=True)
|
" (RID %d), killing", self.rid, exc_info=True)
|
||||||
self.process.kill()
|
self.process.kill()
|
||||||
|
yield from asyncio_process_wait(self.process)
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
yield from asyncio_process_wait_timeout(self.process,
|
yield from asyncio_process_wait_timeout(self.process,
|
||||||
|
@ -108,6 +110,7 @@ class Worker:
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
logger.warning("worker did not exit (RID %d), killing", self.rid)
|
logger.warning("worker did not exit (RID %d), killing", self.rid)
|
||||||
self.process.kill()
|
self.process.kill()
|
||||||
|
yield from asyncio_process_wait(self.process)
|
||||||
else:
|
else:
|
||||||
logger.debug("worker exited gracefully (RID %d)", self.rid)
|
logger.debug("worker exited gracefully (RID %d)", self.rid)
|
||||||
finally:
|
finally:
|
||||||
|
|
|
@ -18,6 +18,7 @@ def parse_arguments(arguments):
|
||||||
d[name] = pyon.decode(value)
|
d[name] = pyon.decode(value)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
def format_arguments(arguments):
|
def format_arguments(arguments):
|
||||||
fmtargs = []
|
fmtargs = []
|
||||||
for k, v in sorted(arguments.items(), key=itemgetter(0)):
|
for k, v in sorted(arguments.items(), key=itemgetter(0)):
|
||||||
|
@ -98,6 +99,14 @@ def asyncio_process_wait_timeout(process, timeout):
|
||||||
timeout=end_time - time.monotonic())
|
timeout=end_time - time.monotonic())
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def asyncio_process_wait(process):
|
||||||
|
r = True
|
||||||
|
while r:
|
||||||
|
f, p = yield from asyncio.wait([process.stdout.read(1024)])
|
||||||
|
r = f.pop().result()
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def asyncio_wait_or_cancel(fs, **kwargs):
|
def asyncio_wait_or_cancel(fs, **kwargs):
|
||||||
fs = [asyncio.async(f) for f in fs]
|
fs = [asyncio.async(f) for f in fs]
|
||||||
|
|
Loading…
Reference in New Issue