@@ -75,63 +75,6 @@ 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
79- static int
80- set_native_thread_name (const char * name )
81- {
82- int rc ;
83- #ifdef __APPLE__
84- rc = pthread_setname_np (name );
85- #elif defined(__NetBSD__ )
86- pthread_t thread = pthread_self ();
87- rc = pthread_setname_np (thread , "%s" , (void * )name );
88- #elif defined(HAVE_PTHREAD_SETNAME_NP )
89- pthread_t thread = pthread_self ();
90- rc = pthread_setname_np (thread , name );
91- #elif defined(HAVE_PTHREAD_SET_NAME_NP )
92- pthread_t thread = pthread_self ();
93- pthread_set_name_np (thread , name );
94- rc = 0 ; /* pthread_set_name_np() returns void */
95- #endif
96- return rc ;
97- }
98-
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 ;
110- }
111- #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 ;
116- }
117- #endif
118- return name_encoded ;
119- }
120-
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
128- }
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 ;
133- }
134-
13578#ifdef MS_WINDOWS
13679typedef HRESULT (WINAPI * PF_GET_THREAD_DESCRIPTION )(HANDLE , PCWSTR * );
13780typedef HRESULT (WINAPI * PF_SET_THREAD_DESCRIPTION )(HANDLE , PCWSTR );
@@ -2636,38 +2579,110 @@ _thread.set_name
26362579Set the name of the current thread.
26372580[clinic start generated code]*/
26382581
2582+ /* Helper to set the thread name using platform-specific APIs */
2583+ static int
2584+ set_native_thread_name (const char * name )
2585+ {
2586+ int rc = 0 ;
2587+ #ifdef __APPLE__
2588+ rc = pthread_setname_np (name );
2589+ #elif defined(__NetBSD__ )
2590+ pthread_t thread = pthread_self ();
2591+ rc = pthread_setname_np (thread , "%s" , (void * )name );
2592+ #elif defined(HAVE_PTHREAD_SETNAME_NP )
2593+ pthread_t thread = pthread_self ();
2594+ rc = pthread_setname_np (thread , name );
2595+ #elif defined(HAVE_PTHREAD_SET_NAME_NP )
2596+ pthread_t thread = pthread_self ();
2597+ pthread_set_name_np (thread , name );
2598+ rc = 0 ; /* pthread_set_name_np() returns void */
2599+ #endif
2600+ return rc ;
2601+ }
2602+
2603+ /* Helper to encode and truncate thread name; returns new reference or NULL */
2604+ static PyObject *
2605+ encode_thread_name (PyObject * name_obj , const char * encoding )
2606+ {
2607+ #ifdef __sun
2608+ /* Solaris always uses UTF-8 */
2609+ encoding = "utf-8" ;
2610+ #endif
2611+
2612+ PyObject * name_encoded = PyUnicode_AsEncodedString (name_obj , encoding , "replace" );
2613+ if (name_encoded == NULL ) {
2614+ return NULL ;
2615+ }
2616+
2617+ #ifdef _PYTHREAD_NAME_MAXLEN
2618+ if (PyBytes_GET_SIZE (name_encoded ) > _PYTHREAD_NAME_MAXLEN ) {
2619+ PyObject * truncated = PyBytes_FromStringAndSize (PyBytes_AS_STRING (name_encoded ),
2620+ _PYTHREAD_NAME_MAXLEN );
2621+ Py_DECREF (name_encoded );
2622+ if (truncated == NULL ) {
2623+ return NULL ;
2624+ }
2625+ return truncated ;
2626+ }
2627+ #endif
2628+
2629+ return name_encoded ;
2630+ }
2631+
2632+ /* Implementation of _thread.set_name */
26392633static PyObject *
26402634_thread_set_name_impl (PyObject * module , PyObject * name_obj )
26412635/*[clinic end generated code: output=402b0c68e0c0daed input=7e7acd98261be82f]*/
26422636{
26432637#ifndef MS_WINDOWS
2638+ #ifdef __sun
2639+ const char * encoding = "utf-8" ;
2640+ #else
26442641 PyInterpreterState * interp = _PyInterpreterState_GET ();
26452642 const char * encoding = interp -> unicode .fs_codec .encoding ;
2646- int rc = set_thread_name_with_encoding (name_obj , encoding );
2643+ #endif
2644+
2645+ /* First attempt using filesystem (or platform) encoding */
2646+ PyObject * name_encoded = encode_thread_name (name_obj , encoding );
2647+ if (name_encoded == NULL ) {
2648+ return NULL ;
2649+ }
2650+ const char * name = PyBytes_AS_STRING (name_encoded );
2651+ int rc = set_native_thread_name (name );
2652+ Py_DECREF (name_encoded );
2653+
2654+ /* If native API refused (EINVAL) and we didn't try ASCII, retry with ASCII. */
26472655 if (rc ) {
26482656 if (rc == EINVAL && strcmp (encoding , "ascii" ) != 0 ) {
2649- rc = set_thread_name_with_encoding (name_obj , "ascii" );
2650- if (rc ) {
2651- errno = rc ;
2652- return PyErr_SetFromErrno (PyExc_OSError );
2657+ PyObject * name_encoded2 = encode_thread_name (name_obj , "ascii" );
2658+ if (name_encoded2 == NULL ) {
2659+ return NULL ;
26532660 }
2654- Py_RETURN_NONE ;
2661+ const char * name2 = PyBytes_AS_STRING (name_encoded2 );
2662+ rc = set_native_thread_name (name2 );
2663+ Py_DECREF (name_encoded2 );
2664+
2665+ if (rc == 0 ) {
2666+ Py_RETURN_NONE ;
2667+ }
2668+ /* if still failing, fall through to raise errno below */
26552669 }
26562670 errno = rc ;
26572671 return PyErr_SetFromErrno (PyExc_OSError );
26582672 }
2673+
26592674 Py_RETURN_NONE ;
26602675#else
2661- // Windows implementation
26622676 assert (pSetThreadDescription != NULL );
2663-
2677+
26642678 Py_ssize_t len ;
26652679 wchar_t * name = PyUnicode_AsWideCharString (name_obj , & len );
26662680 if (name == NULL ) {
26672681 return NULL ;
26682682 }
2683+
26692684 if (len > _PYTHREAD_NAME_MAXLEN ) {
2670- // Truncate the name
2685+ /* Truncate the name */
26712686 Py_UCS4 ch = name [_PYTHREAD_NAME_MAXLEN - 1 ];
26722687 if (Py_UNICODE_IS_HIGH_SURROGATE (ch )) {
26732688 name [_PYTHREAD_NAME_MAXLEN - 1 ] = 0 ;
@@ -2676,6 +2691,7 @@ _thread_set_name_impl(PyObject *module, PyObject *name_obj)
26762691 name [_PYTHREAD_NAME_MAXLEN ] = 0 ;
26772692 }
26782693 }
2694+
26792695 HRESULT hr = pSetThreadDescription (GetCurrentThread (), name );
26802696 PyMem_Free (name );
26812697 if (FAILED (hr )) {
@@ -2685,6 +2701,7 @@ _thread_set_name_impl(PyObject *module, PyObject *name_obj)
26852701 Py_RETURN_NONE ;
26862702#endif
26872703}
2704+
26882705#endif // HAVE_PTHREAD_SETNAME_NP || HAVE_PTHREAD_SET_NAME_NP || MS_WINDOWS
26892706
26902707
0 commit comments