mirror of
https://github.com/yeicor-3d/yet-another-cad-viewer.git
synced 2025-12-19 22:24:17 +01:00
Fix server lifecycle (cleanup)
This commit is contained in:
@@ -2,6 +2,7 @@ import asyncio
|
||||
import atexit
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
from threading import Thread
|
||||
from typing import Optional
|
||||
|
||||
@@ -20,6 +21,7 @@ class Server:
|
||||
app = web.Application()
|
||||
runner: web.AppRunner
|
||||
thread: Optional[Thread] = None
|
||||
do_shutdown = asyncio.Event()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# --- Routes ---
|
||||
@@ -29,11 +31,12 @@ class Server:
|
||||
self.app.router.add_get('/{path:(.*/|)}', _index_handler) # Any folder -> index.html
|
||||
self.app.router.add_static('/', path=FRONTEND_BASE_PATH, name='static_frontend')
|
||||
# --- Misc ---
|
||||
self.runner = web.AppRunner(self.app)
|
||||
self.loop = asyncio.new_event_loop()
|
||||
|
||||
def start(self):
|
||||
"""Starts the web server in the background"""
|
||||
assert self.thread is None, "Server already started"
|
||||
# Start the server in a separate daemon thread
|
||||
self.thread = Thread(target=self.run_server, name='yacv_server', daemon=True)
|
||||
signal.signal(signal.SIGINT | signal.SIGTERM, self.stop)
|
||||
atexit.register(self.stop)
|
||||
@@ -42,23 +45,34 @@ class Server:
|
||||
# noinspection PyUnusedLocal
|
||||
def stop(self, *args):
|
||||
"""Stops the web server"""
|
||||
print('Stopping server...')
|
||||
if self.thread is None:
|
||||
print('Cannot stop server because it is not running')
|
||||
return
|
||||
asyncio.run(self.runner.shutdown())
|
||||
asyncio.run(self.app.cleanup())
|
||||
self.thread = None # FIXME: Not properly cleaned up (join blocks forever)
|
||||
print('Cleanup done')
|
||||
# FIXME: Wait for at least one client to confirm ready before stopping in case we are too fast?
|
||||
self.loop.call_soon_threadsafe(lambda *a: self.do_shutdown.set())
|
||||
self.thread.join(timeout=12)
|
||||
self.thread = None
|
||||
if len(args) >= 1 and args[0] in (signal.SIGINT, signal.SIGTERM):
|
||||
sys.exit(0) # Exit with success
|
||||
|
||||
def run_server(self):
|
||||
"""Runs the web server"""
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
loop.run_until_complete(self.runner.setup())
|
||||
site = web.TCPSite(self.runner, os.getenv('YACV_HOST', 'localhost'), int(os.getenv('YACV_PORT', 32323)))
|
||||
loop.run_until_complete(site.start())
|
||||
loop.run_forever()
|
||||
asyncio.set_event_loop(self.loop)
|
||||
self.loop.run_until_complete(self.run_server_async())
|
||||
self.loop.stop()
|
||||
self.loop.close()
|
||||
|
||||
async def run_server_async(self):
|
||||
"""Runs the web server (async)"""
|
||||
runner = web.AppRunner(self.app)
|
||||
await runner.setup()
|
||||
site = web.TCPSite(runner, os.getenv('YACV_HOST', 'localhost'), int(os.getenv('YACV_PORT', 32323)))
|
||||
await site.start()
|
||||
# print(f'Server started at {site.name}')
|
||||
# Wait for a signal to stop the server while running
|
||||
await self.do_shutdown.wait()
|
||||
# print('Shutting down server...')
|
||||
await runner.cleanup()
|
||||
|
||||
def show_object(self, obj: TopoDS_Shape):
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user