nikolay
nikolay

Reputation: 21

How to stop aiohttp server running in a thread?

I am working on UI app (kivy) and trying to implement python AIOHTTP Server start and stop buttons. I have found example in another post how to start aiohttp server in a thread (main thread is used by UI app). But not sure how to stop the aiohttp server running in a thread, as loop.run_forever is a blocking method.

Thanks in advance.

Python 3.7.0 aiohttp 3.6.2 OS: Windows

Code is:

Serverthread.py

import asyncio
from aiohttp import web


def aiohttp_server():
    print("aiohttp_server runner created")

    async def say_hello(request):
        return web.Response(text='Hello, world')

    app = web.Application()
    app.add_routes([web.get('/', say_hello)])
    runner = web.AppRunner(app)
    return runner


def run_server(runner):
    print("Entering run_server")
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(runner.setup())
    site = web.TCPSite(runner, 'localhost', 8080)
    loop.run_until_complete(site.start())
    print("Loop run_forever")
    loop.run_forever()


def stop_server(runner):
    print("Entering stop_server")

App, my-ui.py

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty, NumericProperty

from serverthread import run_server, aiohttp_server
import threading


class ServerAdmin(Widget):
    active_threads = NumericProperty(0)
    t = ObjectProperty(threading.Thread(target=run_server, args=(aiohttp_server(),), daemon=True))

    def start_server(self):
        if self.active_threads == 0:
            print("starting server...")
            self.t.start()
            self.active_threads += 1
            print("Server thread started.")

        else:
            print("Number of active threads: ", str(self.active_threads))

    def stop_server(self):
        print("stopping server...")
        print(f"Check if thread active: {str(self.t.isAlive())}, {self.t.name}")
        pass


class MyUiApp(App):
    def build(self):
        return ServerAdmin()


if __name__ == '__main__':
    MyUiApp().run()

Upvotes: 2

Views: 1607

Answers (2)

Joril
Joril

Reputation: 20596

Keep a reference to the event loop and then request a call to the same handler that AppRunner uses for handling SIGKILL and SIGTERM

from aiohttp.web_runner import _raise_graceful_exit

loop.call_soon_threadsafe(_raise_graceful_exit)

Upvotes: 0

eri
eri

Reputation: 3524

Share event

class ServerAdmin(Widget):
    stop = ObjectProperty(asyncio.Event())
    t = ObjectProperty(threading.Thread(target=run_server, args=(aiohttp_server(),stop ), daemon=True))

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


def run_server(runner, stop):
    ...
    print("Loop run_forever")
    # loop.run_forever()
    loop.run_until_complete(stop.wait())
    loop.close()

Upvotes: 1

Related Questions