mirror of https://github.com/python/cpython.git
gh-59705: Set OS thread name when Thread.name is changed (#127702)
Co-authored-by: Petr Viktorin <encukou@gmail.com>
This commit is contained in:
parent
9af96f4406
commit
c91ccbe4ac
|
@ -434,6 +434,18 @@ since it is impossible to detect the termination of alien threads.
|
|||
Multiple threads may be given the same name. The initial name is set by
|
||||
the constructor.
|
||||
|
||||
On some platforms, the thread name is set at the operating system level
|
||||
when the thread starts, so that it is visible in task managers.
|
||||
This name may be truncated to fit in a system-specific limit (for example,
|
||||
15 bytes on Linux or 63 bytes on macOS).
|
||||
|
||||
Changes to *name* are only reflected at the OS level when the currently
|
||||
running thread is renamed. (Setting the *name* attribute of a
|
||||
different thread only updates the Python Thread object.)
|
||||
|
||||
.. versionchanged:: 3.14
|
||||
Set the operating system thread name.
|
||||
|
||||
.. method:: getName()
|
||||
setName()
|
||||
|
||||
|
|
|
@ -2164,6 +2164,25 @@ def work():
|
|||
self.assertEqual(work_name, expected,
|
||||
f"{len(work_name)=} and {len(expected)=}")
|
||||
|
||||
@unittest.skipUnless(hasattr(_thread, 'set_name'), "missing _thread.set_name")
|
||||
@unittest.skipUnless(hasattr(_thread, '_get_name'), "missing _thread._get_name")
|
||||
def test_change_name(self):
|
||||
# Change the name of a thread while the thread is running
|
||||
|
||||
name1 = None
|
||||
name2 = None
|
||||
def work():
|
||||
nonlocal name1, name2
|
||||
name1 = _thread._get_name()
|
||||
threading.current_thread().name = "new name"
|
||||
name2 = _thread._get_name()
|
||||
|
||||
thread = threading.Thread(target=work, name="name")
|
||||
thread.start()
|
||||
thread.join()
|
||||
self.assertEqual(name1, "name")
|
||||
self.assertEqual(name2, "new name")
|
||||
|
||||
|
||||
class InterruptMainTests(unittest.TestCase):
|
||||
def check_interrupt_main_with_signal_handler(self, signum):
|
||||
|
|
|
@ -1026,16 +1026,20 @@ def _set_ident(self):
|
|||
def _set_native_id(self):
|
||||
self._native_id = get_native_id()
|
||||
|
||||
def _set_os_name(self):
|
||||
if _set_name is None or not self._name:
|
||||
return
|
||||
try:
|
||||
_set_name(self._name)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def _bootstrap_inner(self):
|
||||
try:
|
||||
self._set_ident()
|
||||
if _HAVE_THREAD_NATIVE_ID:
|
||||
self._set_native_id()
|
||||
if _set_name is not None and self._name:
|
||||
try:
|
||||
_set_name(self._name)
|
||||
except OSError:
|
||||
pass
|
||||
self._set_os_name()
|
||||
self._started.set()
|
||||
with _active_limbo_lock:
|
||||
_active[self._ident] = self
|
||||
|
@ -1115,6 +1119,8 @@ def name(self):
|
|||
def name(self, name):
|
||||
assert self._initialized, "Thread.__init__() not called"
|
||||
self._name = str(name)
|
||||
if get_ident() == self._ident:
|
||||
self._set_os_name()
|
||||
|
||||
@property
|
||||
def ident(self):
|
||||
|
|
|
@ -2423,8 +2423,7 @@ _thread_set_name_impl(PyObject *module, PyObject *name_obj)
|
|||
|
||||
#ifdef PYTHREAD_NAME_MAXLEN
|
||||
// Truncate to PYTHREAD_NAME_MAXLEN bytes + the NUL byte if needed
|
||||
size_t len = PyBytes_GET_SIZE(name_encoded);
|
||||
if (len > PYTHREAD_NAME_MAXLEN) {
|
||||
if (PyBytes_GET_SIZE(name_encoded) > PYTHREAD_NAME_MAXLEN) {
|
||||
PyObject *truncated;
|
||||
truncated = PyBytes_FromStringAndSize(PyBytes_AS_STRING(name_encoded),
|
||||
PYTHREAD_NAME_MAXLEN);
|
||||
|
|
Loading…
Reference in New Issue