diff options
author | ianb <devnull@localhost> | 2007-04-12 04:00:38 +0000 |
---|---|---|
committer | ianb <devnull@localhost> | 2007-04-12 04:00:38 +0000 |
commit | 7ece1ccb1f175a8d2a6d0953bb93fa2215b2ae75 (patch) | |
tree | 22f21e89a5f470eb58a561d353ca7707e11534b3 /paste/httpserver.py | |
parent | e2c41182a57cf9b5ab61784a8ebfdce9a2a0ecff (diff) | |
download | paste-7ece1ccb1f175a8d2a6d0953bb93fa2215b2ae75.tar.gz |
Added a parameter to the threadpool: max_requests, which is the maximum number of requests to process in a worker thread before killing that thread. This should resolve problems with long-lived threads, as no thread lives too terribly long with this on. Also, turn the threadpool back on by default. And turn LimitedLengthFile back on when it is not an SSL connection
Diffstat (limited to 'paste/httpserver.py')
-rwxr-xr-x | paste/httpserver.py | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/paste/httpserver.py b/paste/httpserver.py index 4ac032a..29c2065 100755 --- a/paste/httpserver.py +++ b/paste/httpserver.py @@ -196,12 +196,11 @@ class WSGIHandlerMixin: content_length = int(self.headers.get('Content-Length', '0')) except ValueError: content_length = 0 - # - # @@: LimitedLengthFile is currently broken in connection - # with SSL (sporatic errors that are diffcult to trace, but - # ones that go away when you don't use LimitedLengthFile) - # - #rfile = LimitedLengthFile(rfile, content_length) + if not hasattr(self.connection, 'get_context'): + # @@: LimitedLengthFile is currently broken in connection + # with SSL (sporatic errors that are diffcult to trace, but + # ones that go away when you don't use LimitedLengthFile) + rfile = LimitedLengthFile(rfile, content_length) remote_address = self.client_address[0] self.wsgi_environ = { @@ -526,7 +525,9 @@ class ThreadPool(object): necessarily reliable. This is turned off by default, since it is only a good idea if you've deployed the server with some process watching from above (something similar to daemontools or zdaemon). - + + Each worker thread only processes ``max_requests`` tasks before it + dies and replaces itself with a new worker thread. """ @@ -534,6 +535,7 @@ class ThreadPool(object): def __init__( self, nworkers, name="ThreadPool", daemon=False, + max_requests=100, # threads are killed after this many requests hung_thread_limit=30, # when a thread is marked "hung" kill_thread_limit=1800, # when you kill that hung thread dying_limit=300, # seconds that a kill should take to go into effect (longer than this and the thread is a "zombie") @@ -547,6 +549,7 @@ class ThreadPool(object): Create thread pool with `nworkers` worker threads. """ self.nworkers = nworkers + self.max_requests = max_requests self.name = name self.queue = Queue.Queue() self.workers = [] @@ -798,7 +801,12 @@ class ThreadPool(object): thread_obj = threading.currentThread() thread_id = thread_obj.thread_id = thread.get_ident() self.idle_workers.append(thread_id) + requests_processed = 0 while True: + if self.max_requests and self.max_requests < requests_processed: + # Replace this thread then die + self.add_worker_thread() + break runnable = self.queue.get() if runnable is ThreadPool.SHUTDOWN: self.logger.debug('Worker %s asked to SHUTDOWN', thread_id) @@ -813,6 +821,7 @@ class ThreadPool(object): except ValueError: pass self.worker_tracker[thread_id] = [time.time(), None] + requests_processed += 1 try: try: runnable() @@ -1059,13 +1068,10 @@ class ServerExit(SystemExit): caught) """ -# @@: ThreadPool is currently broken, it shouldn't be the default till -# it is thoroughly tested. -# def serve(application, host=None, port=None, handler=None, ssl_pem=None, ssl_context=None, server_version=None, protocol_version=None, start_loop=True, daemon_threads=None, socket_timeout=None, - use_threadpool=False, threadpool_workers=10, + use_threadpool=True, threadpool_workers=10, threadpool_options=None): """ Serves your ``application`` over HTTP(S) via WSGI interface @@ -1232,7 +1238,8 @@ def server_runner(wsgi_app, global_conf, **kwargs): 'threadpool_kill_thread_limit', 'threadpool_dying_limit', 'threadpool_spawn_if_under', 'threadpool_max_zombie_threads_before_die', - 'threadpool_hung_check_period']: + 'threadpool_hung_check_period', + 'threadpool_max_requests']: if name in kwargs: kwargs[name] = int(kwargs[name]) for name in ['use_threadpool', 'daemon_threads']: @@ -1253,6 +1260,12 @@ server_runner.__doc__ = serve.__doc__ + """ You can also set these threadpool options: + ``threadpool_max_requests``: + + The maximum number of requests a worker thread will process + before dying (and replacing itself with a new worker thread). + Default 100. + ``threadpool_hung_thread_limit``: The number of seconds a thread can work on a task before it is |