network: handle main_taskgroup dying better. passthrough CancelledError

Previously if a task running in the main_taskgroup raised,
main_taskgroup might have never finished as fx.run (another task running
in main_taskgroup) could not be cancelled (it was swallowing the CancelledError).

Need to be careful with catching all Exceptions or BaseExceptions,
as that might result in a coroutine not being cancellable.
Note that from python 3.8 onwards, CancelledError will inherit from BaseException
instead of Exception, so catching all Exceptions is somewhat less horrible
but this will only really matter if we raise the min py version to 3.8...

Really, all "except BaseException" lines are suspect and at least should be
considered for replacement with "except Exception".

-----

regarding fx.run not being cancellable before, and relevant lines, see:

6197cfbb3b/electrum/network.py (L1171)
0decdffce2/aiorpcx/curio.py (L242)
0decdffce2/aiorpcx/curio.py (L199)
0decdffce2/aiorpcx/curio.py (L208)
0decdffce2/aiorpcx/curio.py (L218)
0decdffce2/aiorpcx/curio.py (L221)
6197cfbb3b/electrum/daemon.py (L194)
6197cfbb3b/electrum/daemon.py (L203)
6197cfbb3b/electrum/exchange_rate.py (L507)
6197cfbb3b/electrum/exchange_rate.py (L79)
This commit is contained in:
SomberNight 2019-08-30 19:46:25 +02:00
parent 6197cfbb3b
commit 9e57a59615
No known key found for this signature in database
GPG key ID: B33B5F232C6271E9
3 changed files with 8 additions and 3 deletions

View file

@ -78,6 +78,9 @@ class ExchangeBase(Logger):
self.logger.info(f"getting fx quotes for {ccy}")
self.quotes = await self.get_rates(ccy)
self.logger.info("received fx quotes")
except asyncio.CancelledError:
# CancelledError must be passed-through for cancellation to work
raise
except BaseException as e:
self.logger.info(f"failed fx quotes: {repr(e)}")
self.quotes = {}

View file

@ -1169,8 +1169,8 @@ class Network(Logger):
async with main_taskgroup as group:
await group.spawn(self._maintain_sessions())
[await group.spawn(job) for job in self._jobs]
except Exception as e:
self.logger.exception('')
except BaseException as e:
self.logger.exception('main_taskgroup died.')
raise e
asyncio.run_coroutine_threadsafe(main(), self.asyncio_loop)

View file

@ -983,7 +983,9 @@ def ignore_exceptions(func):
async def wrapper(*args, **kwargs):
try:
return await func(*args, **kwargs)
except BaseException as e:
except asyncio.CancelledError:
raise
except Exception as e:
pass
return wrapper