=> 6ac505666d0d67bd9bfa608111105253b6d7f907
[1mdiff --git a/gmcapsule/__init__.py b/gmcapsule/__init__.py[m [1mindex decc1d8..7a98b98 100644[m [1m--- a/gmcapsule/__init__.py[m [1m+++ b/gmcapsule/__init__.py[m [36m@@ -508,11 +508,16 @@[m [mclass Config:[m """[m [m def __init__(self, config_path):[m [32m+[m[32m self.config_path = config_path[m [32m+[m[32m self.reload()[m [32m+[m [32m+[m[32m def reload(self):[m self.ini = configparser.ConfigParser()[m [31m- if os.path.exists(config_path):[m [31m- self.ini.read(config_path)[m [32m+[m[32m if os.path.exists(self.config_path):[m [32m+[m[32m print('Configuration:', self.config_path)[m [32m+[m[32m self.ini.read(self.config_path)[m else:[m [31m- print(config_path, 'not found -- using defaults')[m [32m+[m[32m print(self.config_path, 'not found -- using defaults')[m [m def hostnames(self):[m """[m [1mdiff --git a/gmcapsule/gemini.py b/gmcapsule/gemini.py[m [1mindex ecddbeb..a7026a0 100644[m [1m--- a/gmcapsule/gemini.py[m [1m+++ b/gmcapsule/gemini.py[m [36m@@ -11,6 +11,7 @@[m [mimport socket[m import threading[m import queue[m import re[m [32m+[m[32mimport signal[m import time[m from pathlib import Path[m from urllib.parse import urlparse[m [36m@@ -659,22 +660,25 @@[m [mclass Worker(threading.Thread):[m return[m [m [m [32m+[m[32m_server_instance = None[m [32m+[m [32m+[m[32mdef _restart_workers(signum, frame):[m [32m+[m[32m if signum == signal.SIGHUP:[m [32m+[m[32m _server_instance.restart_workers()[m [32m+[m [32m+[m class Server:[m def __init__(self, cfg):[m [32m+[m[32m global _server_instance[m [32m+[m[32m assert _server_instance is None[m [32m+[m[32m _server_instance = self[m #mp.set_start_method('spawn')[m [32m+[m[32m self.cfg = cfg[m [32m+[m[32m self.address = cfg.address()[m [32m+[m[32m self.port = cfg.port()[m [m [31m- hostname_or_hostnames = cfg.hostnames()[m cert_path = cfg.certs_dir() / 'cert.pem'[m key_path = cfg.certs_dir() / 'key.pem'[m [31m- address = cfg.address()[m [31m- port = cfg.port()[m [31m- session_id = f'GmCapsule:{cfg.port()}'.encode('utf-8')[m [31m- num_threads = cfg.num_threads()[m [31m-[m [31m- self.hostnames = [hostname_or_hostnames] \[m [31m- if type(hostname_or_hostnames) == str else hostname_or_hostnames[m [31m- self.address = address[m [31m- self.port = port[m [m if not os.path.exists(cert_path):[m raise Exception("certificate file not found: " + str(cert_path))[m [36m@@ -685,22 +689,32 @@[m [mclass Server:[m self.context.use_certificate_file(str(cert_path))[m self.context.use_privatekey_file(str(key_path))[m self.context.set_verify(SSL.VERIFY_PEER, verify_callback)[m [31m- if session_id:[m [31m- if type(session_id) != bytes:[m [31m- raise Exception("session_id type must be `bytes`")[m [31m- self.context.set_session_id(session_id)[m [32m+[m [32m+[m[32m session_id = f'GmCapsule:{cfg.port()}'.encode('utf-8')[m [32m+[m[32m #if type(session_id) != bytes:[m [32m+[m[32m # raise Exception("session_id type must be `bytes`")[m [32m+[m[32m self.context.set_session_id(session_id)[m [m # Spawn the worker threads.[m self.shutdown_event = threading.Event()[m self.workers = [][m self.work_queue = queue.Queue()[m [31m- for worker_id in range(max(num_threads, 1)):[m [31m- worker = Worker(worker_id, cfg, self.work_queue, self.shutdown_event)[m [31m- self.workers.append(worker)[m [32m+[m[32m self.create_workers(cfg)[m [m self.sock = None[m self.sv_conn = None[m [m [32m+[m[32m def restart_workers(self):[m [32m+[m[32m """[m [32m+[m[32m Restarts workers with an updated configuration. The server socket or[m [32m+[m[32m TLS configuration are not modified, even if the values have changed[m [32m+[m[32m in the configuration file.[m [32m+[m[32m """[m [32m+[m[32m self.stop_workers()[m [32m+[m[32m self.cfg.reload()[m [32m+[m[32m self.create_workers(self.cfg)[m [32m+[m[32m self.start_workers()[m [32m+[m def run(self):[m attempts = 60[m print(f'Opening port {self.port}...')[m [36m@@ -720,14 +734,12 @@[m [mclass Server:[m print('...')[m print(f'Server started on port {self.port}')[m [m [31m- PARALLELIZE = True[m [31m-[m [31m- if PARALLELIZE:[m [31m- for worker in self.workers:[m [31m- worker.start()[m [31m- print(len(self.workers), 'worker(s) started')[m [32m+[m[32m self.start_workers()[m [m [31m- snapshot = None[m [32m+[m[32m try:[m [32m+[m[32m signal.signal(signal.SIGHUP, _restart_workers)[m [32m+[m[32m except ValueError:[m [32m+[m[32m print('Restarting with SIGHUP not supported')[m [m while True:[m stream = None[m [36m@@ -735,11 +747,6 @@[m [mclass Server:[m stream, from_addr = self.sv_conn.accept()[m stream._socket.settimeout(10)[m self.work_queue.put((stream, from_addr))[m [31m-[m [31m- if not PARALLELIZE:[m [31m- self.work_queue.put((None, None)) # single iteration only[m [31m- self.workers[0].run()[m [31m-[m del stream[m del from_addr[m except KeyboardInterrupt:[m [36m@@ -756,11 +763,27 @@[m [mclass Server:[m self.sock = None[m [m # Stop all workers.[m [31m- self.shutdown_event.set()[m [31m- if PARALLELIZE:[m [31m- for i in range(len(self.workers)):[m [31m- self.work_queue.put((None, None))[m [31m- for worker in self.workers:[m [31m- worker.join()[m [32m+[m[32m self.stop_workers()[m [m print('Done')[m [32m+[m [32m+[m[32m def create_workers(self, cfg):[m [32m+[m[32m self.shutdown_event.clear()[m [32m+[m[32m for worker_id in range(max(cfg.num_threads(), 1)):[m [32m+[m[32m worker = Worker(worker_id, cfg, self.work_queue, self.shutdown_event)[m [32m+[m[32m self.workers.append(worker)[m [32m+[m [32m+[m[32m def start_workers(self):[m [32m+[m[32m for worker in self.workers:[m [32m+[m[32m worker.start()[m [32m+[m[32m print(len(self.workers), 'worker(s) started')[m [32m+[m [32m+[m[32m def stop_workers(self):[m [32m+[m[32m self.shutdown_event.set()[m [32m+[m[32m n = len(self.workers)[m [32m+[m[32m for _ in range(n):[m [32m+[m[32m self.work_queue.put((None, None))[m [32m+[m[32m for worker in self.workers:[m [32m+[m[32m worker.join()[m [32m+[m[32m self.workers = [][m [32m+[m[32m print(n, 'worker(s) stopped')[m
text/gemini; charset=utf-8
This content has been proxied by September (ba2dc).