testutil: add AtomicCounter() as a threadsafe counter

The existing code in the reqs counting is not really thread safe,
this commit fixes that.
This commit is contained in:
Michael Vogt 2024-04-04 17:18:57 +02:00 committed by Ondřej Budai
parent b90a5027dc
commit b9b296a7e5
4 changed files with 39 additions and 8 deletions

View file

@ -0,0 +1,29 @@
#!/usr/bin/python3
"""
thread/atomic related utilities
"""
import threading
class AtomicCounter:
""" A thread-safe counter """
def __init__(self, count: int = 0) -> None:
self._count = count
self._lock = threading.Lock()
def inc(self) -> None:
""" increase the count """
with self._lock:
self._count += 1
def dec(self) -> None:
""" decrease the count """
with self._lock:
self._count -= 1
@property
def count(self) -> int:
""" get the current count """
with self._lock:
return self._count

View file

@ -7,6 +7,8 @@ import http.server
import socket
import threading
from .atomic import AtomicCounter
def _get_free_port():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@ -23,13 +25,13 @@ class DirHTTPServer(http.server.ThreadingHTTPServer):
def __init__(self, *args, directory=None, simulate_failures=0, **kwargs):
super().__init__(*args, **kwargs)
self.directory = directory
self.simulate_failures = simulate_failures
self.reqs = 0
self.simulate_failures = AtomicCounter(simulate_failures)
self.reqs = AtomicCounter()
def finish_request(self, request, client_address):
self.reqs += 1 # racy on non GIL systems
if self.simulate_failures > 0:
self.simulate_failures -= 1 # racy on non GIL systems
self.reqs.inc()
if self.simulate_failures.count > 0:
self.simulate_failures.dec()
SilentHTTPRequestHandler(
request, client_address, self, directory="does-not-exists")
return