From 415f28b39ef4eb2639fac01273a1007a74aac697 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Wed, 21 Jun 2017 11:25:53 -0700 Subject: [PATCH 1/2] bpo-29212: Fix the ugly repr() TPE thread name. Fixes the newly introduced ugly default thread name for concurrent.futures thread.ThreadPoolExecutor threads. They'll now resemble the old <=3.5 threading default Thread-x names by being named ThreadPoolExecutor-y_n. --- Lib/concurrent/futures/thread.py | 8 +++++++- Lib/test/test_concurrent_futures.py | 7 +++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Lib/concurrent/futures/thread.py b/Lib/concurrent/futures/thread.py index 03d276b63f63cae..1f0a1d4b977f316 100644 --- a/Lib/concurrent/futures/thread.py +++ b/Lib/concurrent/futures/thread.py @@ -7,6 +7,7 @@ import atexit from concurrent.futures import _base +import itertools import queue import threading import weakref @@ -81,6 +82,10 @@ def _worker(executor_reference, work_queue): _base.LOGGER.critical('Exception in worker', exc_info=True) class ThreadPoolExecutor(_base.Executor): + + # Used to assign unique thread names when thread_name_prefix is not supplied. + _counter = itertools.count().__next__ + def __init__(self, max_workers=None, thread_name_prefix=''): """Initializes a new ThreadPoolExecutor instance. @@ -101,7 +106,8 @@ def __init__(self, max_workers=None, thread_name_prefix=''): self._threads = set() self._shutdown = False self._shutdown_lock = threading.Lock() - self._thread_name_prefix = thread_name_prefix + self._thread_name_prefix = (thread_name_prefix or + ("ThreadPoolExecutor-%d" % self._counter())) def submit(self, fn, *args, **kwargs): with self._shutdown_lock: diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index 23e95b212447c86..e2da47bc5828de9 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -172,10 +172,9 @@ def test_thread_names_default(self): del executor for t in threads: - # We don't particularly care what the default name is, just that - # it has a default name implying that it is a ThreadPoolExecutor - # followed by what looks like a thread number. - self.assertRegex(t.name, r'^.*ThreadPoolExecutor.*_[0-4]$') + # Ensure that our default name is reasonably sane and unique when + # no thread_name_prefix was supplied. + self.assertRegex(t.name, r'ThreadPoolExecutor-\d+_[0-4]$') t.join() From 18dbb873c9e2da602fd8b94f1b833e8ca630320e Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Wed, 21 Jun 2017 23:26:04 -0700 Subject: [PATCH 2/2] bpo-29212: add a Misc/NEWS entry. --- Misc/NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Misc/NEWS b/Misc/NEWS index 299d9c2784b67bb..2458522e01582d2 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -368,6 +368,10 @@ Extension Modules Library ------- +- bpo-29212: Fix concurrent.futures.thread.ThreadPoolExecutor threads to have + a non repr() based thread name by default when no thread_name_prefix is + supplied. They will now identify themselves as "ThreadPoolExecutor-y_n". + - [Security] bpo-30694: Upgrade expat copy from 2.2.0 to 2.2.1 to get fixes of multiple security vulnerabilities including: CVE-2017-9233 (External entity infinite loop DoS), CVE-2016-9063 (Integer overflow, re-fix),