util: create_and_start_event_loop() to wait until loop starts
With a PyCharm debugger attached, sometimes the python process is so
CPU-starved for me that create_and_start_event_loop() returned
before the event loop actually started, resulting in weird errors.
I guess this could happen even without a debugger attached on a
sufficiently slow CPU.
```
...\electrum\electrum\wallet.py:3580: in restore_wallet_from_text
wallet = Wallet(db, storage, config=config)
...\electrum\electrum\wallet.py:3501: in __new__
wallet = WalletClass(db, storage, config=config)
...\electrum\electrum\wallet.py:3345: in __init__
Deterministic_Wallet.__init__(self, db, storage, config=config)
...\electrum\electrum\wallet.py:3135: in __init__
self.synchronize()
...\electrum\electrum\wallet.py:3283: in synchronize
count += self.synchronize_sequence(False)
...\electrum\electrum\wallet.py:3267: in synchronize_sequence
self.create_new_address(for_change)
...\electrum\electrum\wallet.py:3254: in create_new_address
self.adb.add_address(address)
...\electrum\electrum\address_synchronizer.py:213: in add_address
self.up_to_date_changed()
...\electrum\electrum\address_synchronizer.py:680: in up_to_date_changed
util.trigger_callback('adb_set_up_to_date', self)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <electrum.util.CallbackManager object at 0x000002B1788AD6F0>
event = 'adb_set_up_to_date'
args = (<electrum.address_synchronizer.AddressSynchronizer object at 0x000002B17A687670>,)
def trigger_callback(self, event, *args):
"""Trigger a callback with given arguments.
Can be called from any thread. The callback itself will get scheduled
on the event loop.
"""
if self.asyncio_loop is None:
self.asyncio_loop = get_asyncio_loop()
> assert self.asyncio_loop.is_running(), "event loop not running"
E AssertionError: event loop not running
...\electrum\electrum\util.py:1734: AssertionError
```
This commit is contained in:
@@ -1556,13 +1556,21 @@ def create_and_start_event_loop() -> Tuple[asyncio.AbstractEventLoop,
|
||||
_asyncio_event_loop = None
|
||||
|
||||
loop.set_exception_handler(on_exception)
|
||||
# loop.set_debug(1)
|
||||
# loop.set_debug(True)
|
||||
stopping_fut = loop.create_future()
|
||||
loop_thread = threading.Thread(
|
||||
target=run_event_loop,
|
||||
name='EventLoop',
|
||||
)
|
||||
loop_thread.start()
|
||||
# Wait until the loop actually starts.
|
||||
# On a slow PC, or with a debugger attached, this can take a few dozens of ms,
|
||||
# and if we returned without a running loop, weird things can happen...
|
||||
t0 = time.monotonic()
|
||||
while not loop.is_running():
|
||||
time.sleep(0.01)
|
||||
if time.monotonic() - t0 > 5:
|
||||
raise Exception("been waiting for 5 seconds but asyncio loop would not start!")
|
||||
return loop, stopping_fut, loop_thread
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user