1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-07 07:12:34 +00:00

src/trezor/loop: avoid closing task from within

This commit is contained in:
Jan Pochyla 2018-06-14 15:03:09 +02:00 committed by Pavol Rusnak
parent 7630201a57
commit 1bfbb34f88

View File

@ -211,7 +211,7 @@ class signal(Syscall):
class spawn(Syscall): class spawn(Syscall):
''' '''
Execute one or more children tasks and wait until one or more of them exit. Execute one or more children tasks and wait until one of them exits.
Return value of `spawn` is the return value of task that triggered the Return value of `spawn` is the return value of task that triggered the
completion. By default, `spawn` returns after the first child completes, and completion. By default, `spawn` returns after the first child completes, and
other running children are killed (by cancelling any pending schedules and other running children are killed (by cancelling any pending schedules and
@ -234,9 +234,8 @@ class spawn(Syscall):
`spawn.__iter__` for explanation. Always use `await`. `spawn.__iter__` for explanation. Always use `await`.
''' '''
def __init__(self, *children, wait_for=1, exit_others=True): def __init__(self, *children, exit_others=True):
self.children = children self.children = children
self.wait_for = wait_for
self.exit_others = exit_others self.exit_others = exit_others
self.scheduled = None # list of scheduled wrapper tasks self.scheduled = None # list of scheduled wrapper tasks
self.finished = None # list of children that finished self.finished = None # list of children that finished
@ -245,28 +244,31 @@ class spawn(Syscall):
def handle(self, task): def handle(self, task):
self.callback = task self.callback = task
self.finished = [] self.finished = []
self.scheduled = [self._wait(c) for c in self.children] self.scheduled = []
for ct in self.scheduled: for index, child in enumerate(self.children):
schedule(ct) parent = self._wait(child, index)
schedule(parent)
self.scheduled.append(parent)
def exit(self): def exit(self, skip_index=-1):
for ct in self.scheduled: for index, parent in enumerate(self.scheduled):
close(ct) if index != skip_index:
close(parent)
async def _wait(self, child): async def _wait(self, child, index):
try: try:
result = await child result = await child
except Exception as e: except Exception as e:
self._finish(child, e) self._finish(child, index, e)
else: else:
self._finish(child, result) self._finish(child, index, result)
def _finish(self, child, result): def _finish(self, child, index, result):
self.finished.append(child) if not self.finished:
if self.wait_for == len(self.finished) or isinstance(result, Exception): self.finished.append(child)
schedule(self.callback, result)
if self.exit_others: if self.exit_others:
self.exit() self.exit(index)
schedule(self.callback, result)
def __iter__(self): def __iter__(self):
try: try: