[3.9] bpo-37193: Remove thread objects which finished process its req… · python/cpython@0e76157
@@ -628,6 +628,39 @@ def server_close(self):
628628self.collect_children(blocking=self.block_on_close)
629629630630631+class _Threads(list):
632+"""
633+ Joinable list of all non-daemon threads.
634+ """
635+def append(self, thread):
636+self.reap()
637+if thread.daemon:
638+return
639+super().append(thread)
640+641+def pop_all(self):
642+self[:], result = [], self[:]
643+return result
644+645+def join(self):
646+for thread in self.pop_all():
647+thread.join()
648+649+def reap(self):
650+self[:] = (thread for thread in self if thread.is_alive())
651+652+653+class _NoThreads:
654+"""
655+ Degenerate version of _Threads.
656+ """
657+def append(self, thread):
658+pass
659+660+def join(self):
661+pass
662+663+631664class ThreadingMixIn:
632665"""Mix-in class to handle each request in a new thread."""
633666@@ -636,9 +669,9 @@ class ThreadingMixIn:
636669daemon_threads = False
637670# If true, server_close() waits until all non-daemonic threads terminate.
638671block_on_close = True
639-# For non-daemonic threads, list of threading.Threading objects
672+# Threads object
640673# used by server_close() to wait for all threads completion.
641-_threads = None
674+_threads = _NoThreads()
642675643676def process_request_thread(self, request, client_address):
644677"""Same as in BaseServer but as a thread.
@@ -655,23 +688,17 @@ def process_request_thread(self, request, client_address):
655688656689def process_request(self, request, client_address):
657690"""Start a new thread to process the request."""
691+if self.block_on_close:
692+vars(self).setdefault('_threads', _Threads())
658693t = threading.Thread(target = self.process_request_thread,
659694args = (request, client_address))
660695t.daemon = self.daemon_threads
661-if not t.daemon and self.block_on_close:
662-if self._threads is None:
663-self._threads = []
664-self._threads.append(t)
696+self._threads.append(t)
665697t.start()
666698667699def server_close(self):
668700super().server_close()
669-if self.block_on_close:
670-threads = self._threads
671-self._threads = None
672-if threads:
673-for thread in threads:
674-thread.join()
701+self._threads.join()
675702676703677704if hasattr(os, "fork"):