81 lines
2.2 KiB
Python
81 lines
2.2 KiB
Python
import platform
|
|
import random
|
|
import signal
|
|
import time
|
|
from multiprocessing import Event, Process
|
|
from typing import Any
|
|
|
|
from .config import Config
|
|
from .typing import WorkerFunc
|
|
from .utils import write_pid_file
|
|
|
|
|
|
def run(config: Config) -> None:
|
|
if config.pid_path is not None:
|
|
write_pid_file(config.pid_path)
|
|
|
|
worker_func: WorkerFunc
|
|
if config.worker_class == "asyncio":
|
|
from .asyncio.run import asyncio_worker
|
|
|
|
worker_func = asyncio_worker
|
|
elif config.worker_class == "uvloop":
|
|
from .asyncio.run import uvloop_worker
|
|
|
|
worker_func = uvloop_worker
|
|
elif config.worker_class == "trio":
|
|
from .trio.run import trio_worker
|
|
|
|
worker_func = trio_worker
|
|
else:
|
|
raise ValueError(f"No worker of class {config.worker_class} exists")
|
|
|
|
if config.workers == 1:
|
|
worker_func(config)
|
|
else:
|
|
run_multiple(config, worker_func)
|
|
|
|
|
|
def run_multiple(config: Config, worker_func: WorkerFunc) -> None:
|
|
if config.use_reloader:
|
|
raise RuntimeError("Reloader can only be used with a single worker")
|
|
|
|
sockets = config.create_sockets()
|
|
|
|
processes = []
|
|
|
|
# Ignore SIGINT before creating the processes, so that they
|
|
# inherit the signal handling. This means that the shutdown
|
|
# function controls the shutdown.
|
|
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
|
|
|
shutdown_event = Event()
|
|
|
|
for _ in range(config.workers):
|
|
process = Process(
|
|
target=worker_func,
|
|
kwargs={"config": config, "shutdown_event": shutdown_event, "sockets": sockets},
|
|
)
|
|
process.daemon = True
|
|
process.start()
|
|
processes.append(process)
|
|
if platform.system() == "Windows":
|
|
time.sleep(0.1 * random.random())
|
|
|
|
def shutdown(*args: Any) -> None:
|
|
shutdown_event.set()
|
|
|
|
for signal_name in {"SIGINT", "SIGTERM", "SIGBREAK"}:
|
|
if hasattr(signal, signal_name):
|
|
signal.signal(getattr(signal, signal_name), shutdown)
|
|
|
|
for process in processes:
|
|
process.join()
|
|
for process in processes:
|
|
process.terminate()
|
|
|
|
for sock in sockets.secure_sockets:
|
|
sock.close()
|
|
for sock in sockets.insecure_sockets:
|
|
sock.close()
|