diff options
Diffstat (limited to 'Lib/socketserver.py')
| -rw-r--r-- | Lib/socketserver.py | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/Lib/socketserver.py b/Lib/socketserver.py index 41a3766772..c4d544b372 100644 --- a/Lib/socketserver.py +++ b/Lib/socketserver.py @@ -547,8 +547,10 @@ if hasattr(os, "fork"): timeout = 300 active_children = None max_children = 40 + # If true, server_close() waits until all child processes complete. + _block_on_close = False - def collect_children(self): + def collect_children(self, *, blocking=False): """Internal routine to wait for children that have exited.""" if self.active_children is None: return @@ -572,7 +574,8 @@ if hasattr(os, "fork"): # Now reap all defunct children. for pid in self.active_children.copy(): try: - pid, _ = os.waitpid(pid, os.WNOHANG) + flags = 0 if blocking else os.WNOHANG + pid, _ = os.waitpid(pid, flags) # if the child hasn't exited yet, pid will be 0 and ignored by # discard() below self.active_children.discard(pid) @@ -621,6 +624,10 @@ if hasattr(os, "fork"): finally: os._exit(status) + def server_close(self): + super().server_close() + self.collect_children(blocking=self._block_on_close) + class ThreadingMixIn: """Mix-in class to handle each request in a new thread.""" @@ -628,6 +635,11 @@ class ThreadingMixIn: # Decides how threads will act upon termination of the # main process daemon_threads = False + # If true, server_close() waits until all non-daemonic threads terminate. + _block_on_close = False + # For non-daemonic threads, list of threading.Threading objects + # used by server_close() to wait for all threads completion. + _threads = None def process_request_thread(self, request, client_address): """Same as in BaseServer but as a thread. @@ -647,8 +659,21 @@ class ThreadingMixIn: t = threading.Thread(target = self.process_request_thread, args = (request, client_address)) t.daemon = self.daemon_threads + if not t.daemon and self._block_on_close: + if self._threads is None: + self._threads = [] + self._threads.append(t) t.start() + def server_close(self): + super().server_close() + if self._block_on_close: + threads = self._threads + self._threads = None + if threads: + for thread in threads: + thread.join() + if hasattr(os, "fork"): class ForkingUDPServer(ForkingMixIn, UDPServer): pass |
