-
-
Notifications
You must be signed in to change notification settings - Fork 32k
gh-59705: Add _thread.set_name() function #127338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 28 commits
c6d324d
63b5d52
9f6a8ab
d79e7af
ebd9752
a7f5651
97ea645
78a9ab9
dcf13f4
6ea7e5a
46721bb
6962116
5d27da0
b713910
5c20ea1
6088b37
3c12d17
bde935f
0584ca3
7508b6c
f4a9f40
ac6d726
08e5922
681624e
f57339f
3941123
2e27043
6ab2944
b370c49
beeae59
ae956a0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
On Linux, :class:`threading.Thread` now sets the thread name to the | ||
operating system. Patch by Victor Stinner. |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -17,6 +17,8 @@ | |||||||
# include <signal.h> // SIGINT | ||||||||
#endif | ||||||||
|
||||||||
#include "clinic/_threadmodule.c.h" | ||||||||
|
||||||||
// ThreadError is just an alias to PyExc_RuntimeError | ||||||||
#define ThreadError PyExc_RuntimeError | ||||||||
|
||||||||
|
@@ -44,6 +46,13 @@ get_thread_state(PyObject *module) | |||||||
return (thread_module_state *)state; | ||||||||
} | ||||||||
|
||||||||
|
||||||||
/*[clinic input] | ||||||||
module _thread | ||||||||
[clinic start generated code]*/ | ||||||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=be8dbe5cc4b16df7]*/ | ||||||||
|
||||||||
|
||||||||
// _ThreadHandle type | ||||||||
|
||||||||
// Handles state transitions according to the following diagram: | ||||||||
|
@@ -2354,6 +2363,95 @@ PyDoc_STRVAR(thread__get_main_thread_ident_doc, | |||||||
Internal only. Return a non-zero integer that uniquely identifies the main thread\n\ | ||||||||
of the main interpreter."); | ||||||||
|
||||||||
|
||||||||
#ifdef HAVE_PTHREAD_GETNAME_NP | ||||||||
/*[clinic input] | ||||||||
_thread._get_name | ||||||||
|
||||||||
Get the name of the current thread. | ||||||||
[clinic start generated code]*/ | ||||||||
|
||||||||
static PyObject * | ||||||||
_thread__get_name_impl(PyObject *module) | ||||||||
/*[clinic end generated code: output=20026e7ee3da3dd7 input=35cec676833d04c8]*/ | ||||||||
{ | ||||||||
// Linux and macOS are limited to respectively 16 and 64 bytes | ||||||||
char name[100]; | ||||||||
pthread_t thread = pthread_self(); | ||||||||
int rc = pthread_getname_np(thread, name, Py_ARRAY_LENGTH(name)); | ||||||||
if (rc) { | ||||||||
errno = rc; | ||||||||
return PyErr_SetFromErrno(PyExc_OSError); | ||||||||
} | ||||||||
|
||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On what platform it does not add the null byte? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The null byte is added on all supported platforms. Before I made sure that the buffer always ended with a null byte, but @serhiy-storchaka asked me to remove it. Let's be optimistic. We can adjust the code later if needed. |
||||||||
#ifdef __sun | ||||||||
return PyUnicode_DecodeUTF8(name, strlen(name), "surrogateescape"); | ||||||||
#else | ||||||||
return PyUnicode_DecodeFSDefault(name); | ||||||||
vstinner marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
#endif | ||||||||
} | ||||||||
#endif // HAVE_PTHREAD_GETNAME_NP | ||||||||
|
||||||||
|
||||||||
#ifdef HAVE_PTHREAD_SETNAME_NP | ||||||||
/*[clinic input] | ||||||||
_thread.set_name | ||||||||
|
||||||||
name as name_obj: unicode | ||||||||
|
||||||||
Set the name of the current thread. | ||||||||
[clinic start generated code]*/ | ||||||||
|
||||||||
static PyObject * | ||||||||
_thread_set_name_impl(PyObject *module, PyObject *name_obj) | ||||||||
/*[clinic end generated code: output=402b0c68e0c0daed input=7e7acd98261be82f]*/ | ||||||||
{ | ||||||||
#ifdef __sun | ||||||||
// Solaris always uses UTF-8 | ||||||||
const char *encoding = "utf-8"; | ||||||||
#else | ||||||||
// Encode the thread name to the filesystem encoding using the "replace" | ||||||||
// error handler | ||||||||
PyInterpreterState *interp = _PyInterpreterState_GET(); | ||||||||
const char *encoding = interp->unicode.fs_codec.encoding; | ||||||||
#endif | ||||||||
PyObject *name_encoded; | ||||||||
name_encoded = PyUnicode_AsEncodedString(name_obj, encoding, "replace"); | ||||||||
if (name_encoded == NULL) { | ||||||||
return NULL; | ||||||||
} | ||||||||
|
||||||||
const char *name = PyBytes_AS_STRING(name_encoded); | ||||||||
#ifdef PYTHREAD_NAME_MAXLEN | ||||||||
// Truncate to PYTHREAD_NAME_MAXLEN bytes + the NUL byte if needed | ||||||||
size_t len = strlen(name); | ||||||||
vstinner marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
if (len > PYTHREAD_NAME_MAXLEN) { | ||||||||
PyObject *truncated = PyBytes_FromStringAndSize(name, PYTHREAD_NAME_MAXLEN); | ||||||||
if (truncated == NULL) { | ||||||||
Py_DECREF(name_encoded); | ||||||||
return NULL; | ||||||||
} | ||||||||
Py_SETREF(name_encoded, truncated); | ||||||||
vstinner marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
name = PyBytes_AS_STRING(name_encoded); | ||||||||
} | ||||||||
#endif | ||||||||
|
||||||||
#ifdef __APPLE__ | ||||||||
int rc = pthread_setname_np(name); | ||||||||
#else | ||||||||
pthread_t thread = pthread_self(); | ||||||||
int rc = pthread_setname_np(thread, name); | ||||||||
#endif | ||||||||
Py_DECREF(name_encoded); | ||||||||
if (rc) { | ||||||||
errno = rc; | ||||||||
return PyErr_SetFromErrno(PyExc_OSError); | ||||||||
} | ||||||||
Py_RETURN_NONE; | ||||||||
} | ||||||||
#endif // HAVE_PTHREAD_SETNAME_NP | ||||||||
|
||||||||
|
||||||||
static PyMethodDef thread_methods[] = { | ||||||||
{"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread, | ||||||||
METH_VARARGS, start_new_thread_doc}, | ||||||||
|
@@ -2393,6 +2491,8 @@ static PyMethodDef thread_methods[] = { | |||||||
METH_O, thread__make_thread_handle_doc}, | ||||||||
{"_get_main_thread_ident", thread__get_main_thread_ident, | ||||||||
METH_NOARGS, thread__get_main_thread_ident_doc}, | ||||||||
_THREAD_SET_NAME_METHODDEF | ||||||||
_THREAD__GET_NAME_METHODDEF | ||||||||
{NULL, NULL} /* sentinel */ | ||||||||
}; | ||||||||
|
||||||||
|
@@ -2484,6 +2584,13 @@ thread_module_exec(PyObject *module) | |||||||
|
||||||||
llist_init(&state->shutdown_handles); | ||||||||
|
||||||||
#ifdef PYTHREAD_NAME_MAXLEN | ||||||||
if (PyModule_AddIntConstant(module, "_NAME_MAXLEN", | ||||||||
PYTHREAD_NAME_MAXLEN) < 0) { | ||||||||
return -1; | ||||||||
} | ||||||||
#endif | ||||||||
|
||||||||
return 0; | ||||||||
} | ||||||||
|
||||||||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.