Skip to content

Commit

Permalink
Explicitly create and remove the event loop
Browse files Browse the repository at this point in the history
  • Loading branch information
agronholm committed Dec 15, 2021
1 parent fd8f804 commit 9015958
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 51 deletions.
2 changes: 2 additions & 0 deletions docs/versionhistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ This library adheres to `Semantic Versioning <http://semver.org/>`_.
- Switched to v0.15+ API of ``ruamel.yaml``
- Switched from ``pkg_resources`` to ``importlib.metadata`` for loading entry points
- Fixed ``DeprecationWarning`` about passing coroutine objects to ``asyncio.wait()``
- Fixed ``DeprecationWarning`` about implicitly creating a new event loop using
``get_event_loop()``

**4.5.0** (2019-03-26)

Expand Down
102 changes: 51 additions & 51 deletions src/asphalt/core/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,62 +81,62 @@ def run_application(component: Union[Component, Dict[str, Any]], *, event_loop_p
logger.info('Switched event loop policy to %s', qualified_name(policy))

# Assign a new default executor with the given max worker thread limit if one was provided
event_loop = asyncio.get_event_loop()
if max_threads is not None:
event_loop.set_default_executor(ThreadPoolExecutor(max_threads))
logger.info('Installed a new thread pool executor with max_workers=%d', max_threads)

# Instantiate the root component if a dict was given
if isinstance(component, dict):
component = cast(Component, component_types.create_object(**component))

logger.info('Starting application')
context = Context()
exception = None # type: Optional[BaseException]
exit_code = 0

# Start the root component
event_loop = asyncio.new_event_loop()
asyncio.set_event_loop(event_loop)
try:
coro = asyncio.wait_for(component.start(context), start_timeout)
event_loop.run_until_complete(coro)
except asyncio.TimeoutError as e:
exception = e
logger.error('Timeout waiting for the root component to start')
exit_code = 1
except Exception as e:
exception = e
logger.exception('Error during application startup')
exit_code = 1
else:
logger.info('Application started')

# Add a signal handler to gracefully deal with SIGTERM
try:
event_loop.add_signal_handler(signal.SIGTERM, sigterm_handler, logger, event_loop)
except NotImplementedError:
pass # Windows does not support signals very well
if max_threads is not None:
event_loop.set_default_executor(ThreadPoolExecutor(max_threads))
logger.info('Installed a new thread pool executor with max_workers=%d', max_threads)

# Finally, run the event loop until the process is terminated or Ctrl+C is pressed
try:
event_loop.run_forever()
except KeyboardInterrupt:
pass
except SystemExit as e:
exit_code = e.code
# Instantiate the root component if a dict was given
if isinstance(component, dict):
component = cast(Component, component_types.create_object(**component))

# Close the root context
logger.info('Stopping application')
event_loop.run_until_complete(context.close(exception))
logger.info('Starting application')
context = Context()
exception = None # type: Optional[BaseException]
exit_code = 0

# Shut down leftover async generators (requires Python 3.6+)
try:
# Start the root component
try:
coro = asyncio.wait_for(component.start(context), start_timeout)
event_loop.run_until_complete(coro)
except asyncio.TimeoutError as e:
exception = e
logger.error('Timeout waiting for the root component to start')
exit_code = 1
except Exception as e:
exception = e
logger.exception('Error during application startup')
exit_code = 1
else:
logger.info('Application started')

# Add a signal handler to gracefully deal with SIGTERM
try:
event_loop.add_signal_handler(signal.SIGTERM, sigterm_handler, logger, event_loop)
except NotImplementedError:
pass # Windows does not support signals very well

# Finally, run the event loop until the process is terminated or Ctrl+C is pressed
try:
event_loop.run_forever()
except KeyboardInterrupt:
pass
except SystemExit as e:
exit_code = e.code

# Close the root context
logger.info('Stopping application')
event_loop.run_until_complete(context.close(exception))

# Shut down leftover async generators
event_loop.run_until_complete(event_loop.shutdown_asyncgens())
except (AttributeError, NotImplementedError):
pass

# Finally, close the event loop itself
event_loop.close()
logger.info('Application stopped')
finally:
# Finally, close the event loop itself
event_loop.close()
asyncio.set_event_loop(None)
logger.info('Application stopped')

# Shut down the logging system
shutdown()
Expand Down

0 comments on commit 9015958

Please sign in to comment.