Skip to content

Commit 1ab9ecd

Browse files
committed
replaced functions with inline code, moved into set_thread_name_with_encoding
1 parent ac3d3dd commit 1ab9ecd

1 file changed

Lines changed: 70 additions & 38 deletions

File tree

Modules/_threadmodule.c

Lines changed: 70 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -75,61 +75,93 @@ get_thread_state_by_cls(PyTypeObject *cls)
7575
return get_thread_state(module);
7676
}
7777

78-
// Helper to set the thread name using platform-specific APIs
7978
static int
80-
set_native_thread_name(const char *name)
79+
set_thread_name_with_encoding(PyObject *name_obj, const char *encoding)
8180
{
82-
int rc;
81+
PyObject *name_encoded = NULL;
82+
83+
#ifndef MS_WINDOWS
84+
/* Determine encoding to use. If encoding arg is NULL, use FS codec. */
85+
const char *enc = encoding;
86+
#ifdef __sun
87+
enc = "utf-8"; /* Solaris always uses UTF-8 */
88+
#else
89+
if (enc == NULL) {
90+
PyInterpreterState *interp = _PyInterpreterState_GET();
91+
enc = interp->unicode.fs_codec.encoding;
92+
}
93+
#endif
94+
95+
name_encoded = PyUnicode_AsEncodedString(name_obj, enc, "replace");
96+
if (name_encoded == NULL) {
97+
return -1; /* Python exception set */
98+
}
99+
100+
#ifdef _PYTHREAD_NAME_MAXLEN
101+
/* Truncate to _PYTHREAD_NAME_MAXLEN bytes if needed */
102+
if (PyBytes_GET_SIZE(name_encoded) > _PYTHREAD_NAME_MAXLEN) {
103+
PyObject *truncated = PyBytes_FromStringAndSize(
104+
PyBytes_AS_STRING(name_encoded),
105+
_PYTHREAD_NAME_MAXLEN);
106+
if (truncated == NULL) {
107+
Py_DECREF(name_encoded);
108+
return -1; /* Python exception set */
109+
}
110+
Py_SETREF(name_encoded, truncated);
111+
}
112+
#endif
113+
114+
const char *name = PyBytes_AS_STRING(name_encoded);
115+
83116
#ifdef __APPLE__
84-
rc = pthread_setname_np(name);
117+
int rc = pthread_setname_np(name);
85118
#elif defined(__NetBSD__)
86119
pthread_t thread = pthread_self();
87-
rc = pthread_setname_np(thread, "%s", (void *)name);
120+
int rc = pthread_setname_np(thread, "%s", (void *)name);
88121
#elif defined(HAVE_PTHREAD_SETNAME_NP)
89122
pthread_t thread = pthread_self();
90-
rc = pthread_setname_np(thread, name);
91-
#elif defined(HAVE_PTHREAD_SET_NAME_NP)
123+
int rc = pthread_setname_np(thread, name);
124+
#else
125+
/* pthread_set_name_np() (void) on some platforms */
92126
pthread_t thread = pthread_self();
127+
int rc = 0;
93128
pthread_set_name_np(thread, name);
94-
rc = 0; /* pthread_set_name_np() returns void */
95129
#endif
96-
return rc;
97-
}
98130

99-
// Helper to encode and truncate thread name
100-
static PyObject *
101-
encode_thread_name(PyObject *name_obj, const char *encoding)
102-
{
103-
#ifdef __sun
104-
// Solaris always uses UTF-8
105-
encoding = "utf-8";
106-
#endif
107-
PyObject *name_encoded = PyUnicode_AsEncodedString(name_obj, encoding, "replace");
108-
if (name_encoded == NULL) {
109-
return NULL;
131+
Py_DECREF(name_encoded);
132+
return rc; /* 0 on success, errno-style >0 on error */
133+
#else
134+
/* Windows: convert to wide string and call SetThreadDescription */
135+
assert(pSetThreadDescription != NULL);
136+
Py_ssize_t len;
137+
wchar_t *wname = PyUnicode_AsWideCharString(name_obj, &len);
138+
if (wname == NULL) {
139+
return -1; /* Python exception set */
110140
}
141+
142+
/* Truncate if necessary (len is number of wchar_t characters) */
111143
#ifdef _PYTHREAD_NAME_MAXLEN
112-
if (PyBytes_GET_SIZE(name_encoded) > _PYTHREAD_NAME_MAXLEN) {
113-
PyObject *truncated = PyBytes_FromStringAndSize(PyBytes_AS_STRING(name_encoded), _PYTHREAD_NAME_MAXLEN);
114-
Py_DECREF(name_encoded);
115-
return truncated;
144+
if (len > _PYTHREAD_NAME_MAXLEN) {
145+
/* Ensure we null-terminate safely. Use maxlen as max characters allowed. */
146+
/* If the char at max-1 is a high surrogate, avoid chopping the surrogate pair. */
147+
Py_UCS4 ch = (Py_UCS4)wname[_PYTHREAD_NAME_MAXLEN - 1];
148+
if (Py_UNICODE_IS_HIGH_SURROGATE(ch) && _PYTHREAD_NAME_MAXLEN >= 2) {
149+
wname[_PYTHREAD_NAME_MAXLEN - 1] = L'\0';
150+
} else {
151+
wname[_PYTHREAD_NAME_MAXLEN] = L'\0';
152+
}
116153
}
117154
#endif
118-
return name_encoded;
119-
}
120155

121-
// Helper to encode, set, and cleanup thread name in one step
122-
static int
123-
set_thread_name_with_encoding(PyObject *name_obj, const char *encoding)
124-
{
125-
PyObject *name_encoded = encode_thread_name(name_obj, encoding);
126-
if (name_encoded == NULL) {
127-
return -1; // error, exception set
156+
HRESULT hr = pSetThreadDescription(GetCurrentThread(), wname);
157+
PyMem_Free(wname);
158+
if (FAILED(hr)) {
159+
/* Convert to a Python exception and return -1 so caller propagates it */
160+
PyErr_SetFromWindowsErr((int)hr);
161+
return -1;
128162
}
129-
const char *name = PyBytes_AS_STRING(name_encoded);
130-
int rc = set_native_thread_name(name);
131-
Py_DECREF(name_encoded);
132-
return rc;
163+
return 0;
164+
#endif
133165
}
134166

135167
#ifdef MS_WINDOWS

0 commit comments

Comments
 (0)