=> 9d266a5cb3d1f4d0251e903b7a6f79079774777f
[1mdiff --git a/gmcapsule/gemini.py b/gmcapsule/gemini.py[m [1mindex dcb17d9..ecddbeb 100644[m [1m--- a/gmcapsule/gemini.py[m [1m+++ b/gmcapsule/gemini.py[m [36m@@ -7,7 +7,9 @@[m [mimport importlib[m import os.path[m import select[m import socket[m [31m-import multiprocessing as mp[m [32m+[m[32m#import multiprocessing as mp[m [32m+[m[32mimport threading[m [32m+[m[32mimport queue[m import re[m import time[m from pathlib import Path[m [36m@@ -303,12 +305,21 @@[m [mclass WorkerContext:[m self.caches = [][m self.is_quiet = False[m [m [31m- def set_quiet(self, is_quiet):[m [31m- self.is_quiet = is_quiet[m [31m-[m def config(self):[m return self.cfg[m [m [32m+[m[32m def shutdown_event(self):[m [32m+[m[32m """[m [32m+[m[32m Returns:[m [32m+[m[32m threading.Event: Event that is set when the server is[m [32m+[m[32m shutting down. Background workers must wait on this and stop[m [32m+[m[32m when the event is set.[m [32m+[m[32m """[m [32m+[m[32m return self.shutdown[m [32m+[m [32m+[m[32m def set_quiet(self, is_quiet):[m [32m+[m[32m self.is_quiet = is_quiet[m [32m+[m def print(self, *args):[m if not self.is_quiet:[m print(*args)[m [36m@@ -396,14 +407,24 @@[m [mclass WorkerContext:[m self.print(f'Init:', mod.__doc__ if mod.__doc__ else name)[m mod.init(self)[m [m [31m- def shutdown_event(self):[m [31m- """[m [31m- Returns:[m [31m- threading.Event: Event that is set when the server is[m [31m- shutting down. Background workers must wait on this and stop[m [31m- when the event is set.[m [31m- """[m [31m- return self.shutdown[m [32m+[m[32m def find_entrypoint(self, protocol, hostname, path):[m [32m+[m[32m try:[m [32m+[m[32m for entry in self.entrypoints[protocol][hostname]:[m [32m+[m[32m path_pattern, handler = entry[m [32m+[m[32m if handler != None:[m [32m+[m[32m # A path string, possibly with wildcards.[m [32m+[m[32m if len(path_pattern) == 0 or fnmatch.fnmatch(path, path_pattern):[m [32m+[m[32m return handler[m [32m+[m[32m else:[m [32m+[m[32m # A callable generic path matcher.[m [32m+[m[32m handler = path_pattern(path)[m [32m+[m[32m if handler:[m [32m+[m[32m return handler[m [32m+[m[32m except Exception as x:[m [32m+[m[32m print(x)[m [32m+[m[32m return None[m [32m+[m [32m+[m[32m return None[m [m def call_entrypoint(self, request):[m """[m [36m@@ -448,11 +469,12 @@[m [mclass WorkerContext:[m raise GeminiError(50, 'Permanent failure')[m [m [m [31m-class Worker(mp.Process):[m [31m- """Process that handles incoming requests from clients."""[m [32m+[m[32mclass Worker(threading.Thread):[m [32m+[m[32m """Thread that handles incoming requests from clients."""[m [m def __init__(self, id, cfg, work_queue, shutdown_event):[m [31m- super().__init__(target=Worker._run, args=(self,))[m [32m+[m[32m #super().__init__(target=Worker._run, args=(self,)) # mp[m [32m+[m[32m super().__init__()[m self.id = id[m self.cfg = cfg[m self.port = cfg.port()[m [36m@@ -460,7 +482,7 @@[m [mclass Worker(mp.Process):[m self.context.set_quiet(id > 0)[m self.jobs = work_queue[m [m [31m- def _run(self):[m [32m+[m[32m def run(self):[m try:[m # Extensions are initialized in the worker process.[m self.context.load_modules()[m [36m@@ -624,7 +646,7 @@[m [mclass Worker(mp.Process):[m # Save to cache.[m if not from_cache and status == 20 and \[m (type(response_data) == bytes or type(response_data) == bytearray):[m [31m- for cache in self.server.caches:[m [32m+[m[32m for cache in self.context.caches:[m if cache.save(hostname + path, meta, response_data):[m break[m [m [36m@@ -639,7 +661,7 @@[m [mclass Worker(mp.Process):[m [m class Server:[m def __init__(self, cfg):[m [31m- mp.set_start_method('spawn')[m [32m+[m[32m #mp.set_start_method('spawn')[m [m hostname_or_hostnames = cfg.hostnames()[m cert_path = cfg.certs_dir() / 'cert.pem'[m [36m@@ -653,10 +675,6 @@[m [mclass Server:[m if type(hostname_or_hostnames) == str else hostname_or_hostnames[m self.address = address[m self.port = port[m [31m- #if cache:[m [31m- # self.caches.append(cache)[m [31m- #self.max_upload_size = max_upload_size[m [31m- #self.require_upload_identity = require_upload_identity[m [m if not os.path.exists(cert_path):[m raise Exception("certificate file not found: " + str(cert_path))[m [36m@@ -673,9 +691,9 @@[m [mclass Server:[m self.context.set_session_id(session_id)[m [m # Spawn the worker threads.[m [31m- self.shutdown_event = mp.Event()[m [32m+[m[32m self.shutdown_event = threading.Event()[m self.workers = [][m [31m- self.work_queue = mp.Queue()[m [32m+[m[32m self.work_queue = queue.Queue()[m for worker_id in range(max(num_threads, 1)):[m worker = Worker(worker_id, cfg, self.work_queue, self.shutdown_event)[m self.workers.append(worker)[m [36m@@ -702,9 +720,9 @@[m [mclass Server:[m print('...')[m print(f'Server started on port {self.port}')[m [m [31m- MULTIPROCESS = True[m [32m+[m[32m PARALLELIZE = True[m [m [31m- if MULTIPROCESS:[m [32m+[m[32m if PARALLELIZE:[m for worker in self.workers:[m worker.start()[m print(len(self.workers), 'worker(s) started')[m [36m@@ -718,7 +736,7 @@[m [mclass Server:[m stream._socket.settimeout(10)[m self.work_queue.put((stream, from_addr))[m [m [31m- if not MULTIPROCESS:[m [32m+[m[32m if not PARALLELIZE:[m self.work_queue.put((None, None)) # single iteration only[m self.workers[0].run()[m [m [36m@@ -739,29 +757,10 @@[m [mclass Server:[m [m # Stop all workers.[m self.shutdown_event.set()[m [31m- if MULTIPROCESS:[m [32m+[m[32m if PARALLELIZE:[m for i in range(len(self.workers)):[m self.work_queue.put((None, None))[m for worker in self.workers:[m worker.join()[m [m print('Done')[m [31m-[m [31m- def find_entrypoint(self, protocol, hostname, path):[m [31m- try:[m [31m- for entry in self.entrypoints[protocol][hostname]:[m [31m- path_pattern, handler = entry[m [31m- if handler != None:[m [31m- # A path string, possibly with wildcards.[m [31m- if len(path_pattern) == 0 or fnmatch.fnmatch(path, path_pattern):[m [31m- return handler[m [31m- else:[m [31m- # A callable generic path matcher.[m [31m- handler = path_pattern(path)[m [31m- if handler:[m [31m- return handler[m [31m- except Exception as x:[m [31m- print(x)[m [31m- return None[m [31m-[m [31m- return None[m
text/gemini; charset=utf-8
This content has been proxied by September (ba2dc).