Remove last globals, be actually re-entrant

This commit is contained in:
Juhani Haverinen 2016-08-02 00:30:46 +03:00
parent dbcd1ee014
commit 0e1cb2952d
1 changed files with 31 additions and 23 deletions

View File

@ -133,13 +133,10 @@ def get_request(sock, *, config):
path = '' path = ''
return path, Protocol.gopher, None return path, Protocol.gopher, None
# Global variables to keep track of the amount of running worker threads
threads_amount = 0
threads_lock = threading.Lock()
# Worker thread implementation # Worker thread implementation
class Serve(threading.Thread): class Serve(threading.Thread):
def __init__(self, sock, address, config): def __init__(self, controller, sock, address, config):
self.controller = controller
self.sock = sock self.sock = sock
self.address = address self.address = address
self.config = config self.config = config
@ -159,25 +156,33 @@ class Serve(threading.Thread):
error('Worker thread (%s) died with: %s' % (self.address, err)) error('Worker thread (%s) died with: %s' % (self.address, err))
finally: finally:
self.sock.close() self.sock.close()
with threads_lock: self.controller.thread_end()
threads_amount -= 1
# spawn_thread(sock, address, config) class Threads_controller:
# Spawn a new thread to serve a connection if possible, do nothing if not def __init__(self):
def spawn_thread(sock, address, config): self.threads_amount = 0
global threads_amount, threads_lock self.threads_lock = threading.Lock()
# See if we can spawn a new thread. If not, log an error, close the socket and return. If yes, increment the amount of threads running
with threads_lock:
if threads_amount >= config.max_threads:
error('Could not serve a request from %s, worker thread limit exhausted' % address)
sock.close()
return
else:
threads_amount += 1
# Spawn a new worker thread # .spawn_thread(sock, address, config)
Serve(sock, address, config).start() # Spawn a new thread to serve a connection if possible, do nothing if not
def spawn_thread(self, sock, address, config):
# See if we can spawn a new thread. If not, log an error, close the socket and return. If yes, increment the amount of threads running
with self.threads_lock:
if self.threads_amount >= config.max_threads:
error('Could not serve a request from %s, worker thread limit exhausted' % address)
sock.close()
return
else:
self.threads_amount += 1
# Spawn a new worker thread
Serve(self, sock, address, config).start()
# .thread_end()
# Called from worker thread to signal it's exiting
def thread_end(self):
with self.threads_lock:
self.threads_amount -= 1
# listen(config) → (Never returns) # listen(config) → (Never returns)
# Binds itself to all interfaces on designated port and listens on incoming connections # Binds itself to all interfaces on designated port and listens on incoming connections
@ -199,6 +204,9 @@ def listen(config):
listening.register(s, select.POLLIN) listening.register(s, select.POLLIN)
sock_by_fd[s.fileno()] = s sock_by_fd[s.fileno()] = s
del listening_sockets del listening_sockets
# Create a controller object for the worker threads
threads_controller = Threads_controller()
while True: while True:
# Wait for listening sockets to get activity # Wait for listening sockets to get activity
@ -213,7 +221,7 @@ def listen(config):
# Set timeout for socket # Set timeout for socket
conn.settimeout(config.socket_timeout) conn.settimeout(config.socket_timeout)
spawn_thread(conn, addr[0], config) threads_controller.spawn_thread(conn, addr[0], config)
if __name__ == '__main__': if __name__ == '__main__':
listen(default_config) listen(default_config)