0

I am building a WebRTC app using aiortc package.

In the app, the client connects to the server using this library and streams video.

My problem is shutting down the server. I have tried multiple options that I saw online but only got a new exception every time...

My code is based on this post

My server code:

import asyncio
import datetime
from asyncio import Event
from asyncio.base_futures import CancelledError

from aiohttp import web
from aiohttp.web_runner import AppRunner

import web_rtc

_event: Event
_site: web.TCPSite
app: web.Application
runner: AppRunner
loop: asyncio.AbstractEventLoop


async def start_server1(host, port):
    global loop
    loop = asyncio.get_running_loop()
    global _event, _site, runner
    # Source: https://newbedev.com/how-to-run-an-aiohttp-server-in-a-thread
    runner = _get_app_runner()
    await runner.setup()
    _site = web.TCPSite(runner, host, port)
    await _site.start()

    # wait forever
    _event = asyncio.Event()
    await _event.wait()


def start_server(host, port):
    try:
        asyncio.run(start_server1(host, port))
    except CancelledError:
        print('Server is down')


def stop_server():
    for task in asyncio.tasks.all_tasks(app._loop):
        print(f'Task {task.cancel()}')

    print('Set')
    _event.set()
    asyncio.run(do_close())


async def do_close():
    print('App')
    await app.shutdown()
    for task in asyncio.all_tasks(loop):
        print(f'- Task {task.cancel()}')

    print('runner')
    await runner.shutdown()
    print('Site')
    await _site.stop()
    print('Loop')
    await loop.shutdown_asyncgens()
    loop.stop()
    print(loop.is_running(), loop.is_closed())
    # loop.close()


async def _main_page_response(_):
    return web.Response(content_type='text/plain', text=f'Hello and welcome {datetime.datetime.now()}')


# region Private functions
def _get_app_runner() -> web.AppRunner:
    global app
    app = web.Application()
    app.on_shutdown.append(_on_shutdown)
    app.router.add_get("/", _main_page_response)
    app.router.add_post("/offer", web_rtc.process_offer)
    app._set_loop(asyncio.get_event_loop())
    return web.AppRunner(app)


async def _on_shutdown(_):
    print('SHUTTING DOWN APP')
    await web_rtc.shutdown()
# endregion

My main method code that runs the server:

import threading
import server
# Another script I have that simply handles with the configuration file
from Code.CoreProduct import config


class StoppableThread(threading.Thread):
    """
        Source: https://stackoverflow.com/a/325528/9977758
        Thread class with a stop() method. The thread itself has to check
        regularly for the stopped() condition.
    """

    def __init__(self, *args, **kwargs):
        super(StoppableThread, self).__init__(*args, **kwargs)
        self._stop_event = threading.Event()

    def stop(self):
        self._stop_event.set()

    def stopped(self):
        return self._stop_event.is_set()


def main():
    print('Reading configuration file')
    cfg = config.get_config()
    print('Initializing inference parameters')
    print(f'Server address: http://{cfg.SERVER.HOST}:{cfg.SERVER.PORT}')

    server_thread = StoppableThread(target=server.start_server, args=(cfg.SERVER.HOST, cfg.SERVER.PORT))
    print('Starting the thread')
    server_thread.start()

    try:
        # Wait until the shutdown key is pressed
        while input('Press X to stop the server:\t') != 'X':
            pass
    finally:  # Make sure we shutdown the server and stopping the thread.
        server.stop_server()
        server_thread.stop()


if __name__ == '__main__':
    main()

The code starts the server on a new thread and waits for the user to press X.

The problem is the stop_server function in the server code, it keeps raising exceptions.

After I send a get-request to the server, the shutdown function raises RuntimeError: Timeout context manager should be used inside a task on the line with await _site.stop()

SagiZiv
  • 784
  • 1
  • 9
  • 29

0 Answers0