From bbf2f0dd36d3a71f562a784a135abedb8e914344 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 20 Nov 2023 15:48:38 +0100 Subject: [PATCH] with help/side-comments from alex i fixed the concurrent account creation problem --- chatmaild/pyproject.toml | 3 +++ chatmaild/src/chatmaild/doveauth.py | 24 ++++++++++++++-------- tests/chatmaild/test_doveauth.py | 32 ++++++++++++++++------------- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/chatmaild/pyproject.toml b/chatmaild/pyproject.toml index 8655149..5e74f5c 100644 --- a/chatmaild/pyproject.toml +++ b/chatmaild/pyproject.toml @@ -15,6 +15,9 @@ filtermail = "chatmaild.filtermail:main" [tool.pytest.ini_options] addopts = "-v -ra --strict-markers" +log_format = "%(asctime)s %(levelname)s %(message)s" +log_date_format = "%Y-%m-%d %H:%M:%S" +log_level = "INFO" [tool.tox] legacy_tox_ini = """ diff --git a/chatmaild/src/chatmaild/doveauth.py b/chatmaild/src/chatmaild/doveauth.py index 208785a..6a93dcc 100644 --- a/chatmaild/src/chatmaild/doveauth.py +++ b/chatmaild/src/chatmaild/doveauth.py @@ -116,7 +116,7 @@ def handle_dovecot_request(msg, db, mail_domain): class ThreadedUnixStreamServer(ThreadingMixIn, UnixStreamServer): - pass + request_queue_size = 100 def main(): @@ -128,14 +128,20 @@ def main(): class Handler(StreamRequestHandler): def handle(self): - while True: - msg = self.rfile.readline().strip().decode() - if not msg: - break - res = handle_dovecot_request(msg, db, mail_domain) - if res: - self.wfile.write(res.encode("ascii")) - self.wfile.flush() + try: + while True: + msg = self.rfile.readline().strip().decode() + if not msg: + break + res = handle_dovecot_request(msg, db, mail_domain) + if res: + self.wfile.write(res.encode("ascii")) + self.wfile.flush() + else: + logging.warn("request had no answer: %r", msg) + except Exception: + logging.exception() + raise try: os.unlink(socket) diff --git a/tests/chatmaild/test_doveauth.py b/tests/chatmaild/test_doveauth.py index e15b5af..b51ebe6 100644 --- a/tests/chatmaild/test_doveauth.py +++ b/tests/chatmaild/test_doveauth.py @@ -1,5 +1,5 @@ import json - +import sys import pytest import threading import queue @@ -60,27 +60,31 @@ def test_handle_dovecot_request(db): assert userdata["password"].startswith("{SHA512-CRYPT}") -def test_100_concurrent_lookups(db): - num = 100 - dbs = [Database(db.path) for i in range(num)] - print(f"created {num} databases") +def test_100_concurrent_lookups_different_accounts(db, gencreds): + num_threads = 100 + req_per_thread = 5 results = queue.Queue() def lookup(db): - try: - lookup_passdb(db, "something@c1.testrun.org", "Pieg9aeToe3eghuthe5u") - except Exception: - results.put(traceback.format_exc()) - else: - results.put(None) + for i in range(req_per_thread): + addr, password = gencreds() + try: + lookup_passdb(db, addr, password) + except Exception: + results.put(traceback.format_exc()) + else: + results.put(None) - threads = [threading.Thread(target=lookup, args=(db,), daemon=True) for db in dbs] + threads = [] + for i in range(num_threads): + thread = threading.Thread(target=lookup, args=(db,), daemon=True) + threads.append(thread) - print(f"created {num} threads, starting them and waiting for results") + print(f"created {num_threads} threads, starting them and waiting for results") for thread in threads: thread.start() - for _ in dbs: + for i in range(num_threads * req_per_thread): res = results.get() if res is not None: pytest.fail(f"concurrent lookup failed\n{res}")