@@ -76,6 +76,7 @@ get_thread_state_by_cls(PyTypeObject *cls)
7676    return  get_thread_state (module );
7777}
7878
79+ 
7980#ifdef  MS_WINDOWS 
8081typedef  HRESULT  (WINAPI  * PF_GET_THREAD_DESCRIPTION )(HANDLE , PCWSTR * );
8182typedef  HRESULT  (WINAPI  * PF_SET_THREAD_DESCRIPTION )(HANDLE , PCWSTR );
@@ -2521,11 +2522,38 @@ of the main interpreter.");
25212522#   include  <pthread_np.h> 
25222523#endif 
25232524
2524- /* Helper to set the thread name using platform-specific APIs */ 
2525+ /* Helper: encode/truncate and call native API to set thread name. 
2526+  * Return: 
2527+  *   0  : success 
2528+  *   >0 : errno-style native error code (e.g. EINVAL) 
2529+  *  -1  : Python-level error (an exception has been set) 
2530+  */ 
25252531static  int 
2526- set_native_thread_name ( const  char  * name )
2532+ set_encoded_thread_name ( PyObject   * name_obj ,  const  char  * encoding )
25272533{
2534+     PyObject  * name_encoded  =  PyUnicode_AsEncodedString (name_obj , encoding , "replace" );
2535+     if  (name_encoded  ==  NULL ) {
2536+         /* PyUnicode_AsEncodedString set an exception */ 
2537+         return  -1 ;
2538+     }
2539+ 
2540+ #ifdef  _PYTHREAD_NAME_MAXLEN 
2541+     if  (PyBytes_GET_SIZE (name_encoded ) >  _PYTHREAD_NAME_MAXLEN ) {
2542+         PyObject  * truncated  =  PyBytes_FromStringAndSize (
2543+             PyBytes_AS_STRING (name_encoded ),
2544+             _PYTHREAD_NAME_MAXLEN );
2545+         Py_DECREF (name_encoded );
2546+         if  (truncated  ==  NULL ) {
2547+             /* PyBytes_FromStringAndSize set an exception */ 
2548+             return  -1 ;
2549+         }
2550+         name_encoded  =  truncated ;
2551+     }
2552+ #endif 
2553+ 
2554+     const  char  * name  =  PyBytes_AS_STRING (name_encoded );
25282555    int  rc  =  0 ;
2556+ 
25292557#ifdef  __APPLE__ 
25302558    rc  =  pthread_setname_np (name );
25312559#elif  defined(__NetBSD__ )
@@ -2537,33 +2565,13 @@ set_native_thread_name(const char *name)
25372565#elif  defined(HAVE_PTHREAD_SET_NAME_NP )
25382566    pthread_t  thread  =  pthread_self ();
25392567    pthread_set_name_np (thread , name );
2540-     rc  =  0 ; /* pthread_set_name_np() returns void */ 
2541- #endif 
2542-     return  rc ;
2543- }
2544- 
2545- /* Helper to encode and truncate thread name */ 
2546- static  PyObject  * 
2547- encode_thread_name (PyObject  * name_obj , const  char  * encoding )
2548- {
2549-     PyObject  * name_encoded  =  PyUnicode_AsEncodedString (name_obj , encoding , "replace" );
2550-     if  (name_encoded  ==  NULL ) {
2551-         return  NULL ;
2552-     }
2553- 
2554- #ifdef  _PYTHREAD_NAME_MAXLEN 
2555-     if  (PyBytes_GET_SIZE (name_encoded ) >  _PYTHREAD_NAME_MAXLEN ) {
2556-         PyObject  * truncated  =  PyBytes_FromStringAndSize (PyBytes_AS_STRING (name_encoded ),
2557-                                                         _PYTHREAD_NAME_MAXLEN );
2558-         Py_DECREF (name_encoded );
2559-         if  (truncated  ==  NULL ) {
2560-             return  NULL ;
2561-         }
2562-         return  truncated ;
2563-     }
2568+     rc  =  0 ; /* that API returns void */ 
2569+ #else 
2570+     rc  =  0 ; /* no-op if platform unsupported */ 
25642571#endif 
25652572
2566-     return  name_encoded ;
2573+     Py_DECREF (name_encoded );
2574+     return  rc ;
25672575}
25682576
25692577#if  defined(HAVE_PTHREAD_GETNAME_NP ) ||  defined(HAVE_PTHREAD_GET_NAME_NP ) ||  defined(MS_WINDOWS )
@@ -2627,48 +2635,51 @@ Set the name of the current thread.
26272635
26282636static  PyObject  * 
26292637_thread_set_name_impl (PyObject  * module , PyObject  * name_obj )
2630- /*[clinic end generated code: output=402b0c68e0c0daed input=7e7acd98261be82f]*/ 
26312638{
26322639#ifndef  MS_WINDOWS 
26332640#ifdef  __sun 
26342641    // Solaris always uses UTF-8 
26352642    const  char  * encoding  =  "utf-8" ;
26362643#else 
2644+     // Encode the thread name to the filesystem encoding using the "replace" 
2645+     // error handler 
26372646    PyInterpreterState  * interp  =  _PyInterpreterState_GET ();
26382647    const  char  * encoding  =  interp -> unicode .fs_codec .encoding ;
26392648#endif 
26402649
2641-     /* First attempt using filesystem (or platform) encoding */ 
2642-     PyObject  * name_encoded  =  encode_thread_name (name_obj , encoding );
2643-     if  (name_encoded  ==  NULL ) {
2650+     int  rc  =  set_encoded_thread_name (name_obj , encoding );
2651+     if  (rc  ==  -1 ) {
2652+         /* Confirm a Python exception was set by the helper. 
2653+            If not, convert to a runtime error (defensive). */ 
2654+         if  (PyErr_Occurred ()) {
2655+             return  NULL ;
2656+         }
2657+         PyErr_SetString (PyExc_RuntimeError , "internal error in set_encoded_thread_name" );
26442658        return  NULL ;
26452659    }
2646-     const  char  * name  =  PyBytes_AS_STRING (name_encoded );
2647-     int  rc  =  set_native_thread_name (name );
2648-     Py_DECREF (name_encoded );
26492660
2650-     /* If native API refused (EINVAL) and we didn't try ASCII, retry with ASCII. */ 
26512661    if  (rc ) {
2662+         /* If native API refused (EINVAL) and we didn't try ASCII, retry with ASCII. */ 
26522663        if  (rc  ==  EINVAL  &&  strcmp (encoding , "ascii" ) !=  0 ) {
2653-             PyObject  * name_encoded2  =  encode_thread_name (name_obj , "ascii" );
2654-             if  (name_encoded2  ==  NULL ) {
2664+             rc  =  set_encoded_thread_name (name_obj , "ascii" );
2665+             if  (rc  ==  -1 ) {
2666+                 if  (PyErr_Occurred ()) {
2667+                     return  NULL ;
2668+                 }
2669+                 PyErr_SetString (PyExc_RuntimeError , "internal error in set_encoded_thread_name" );
26552670                return  NULL ;
26562671            }
2657-             const  char  * name2  =  PyBytes_AS_STRING (name_encoded2 );
2658-             rc  =  set_native_thread_name (name2 );
2659-             Py_DECREF (name_encoded2 );
2660- 
26612672            if  (rc  ==  0 ) {
26622673                Py_RETURN_NONE ;
26632674            }
2664-             /* if still failing,  fall through to raise errno below */ 
2675+             /* fall through to raise errno below */ 
26652676        }
26662677        errno  =  rc ;
26672678        return  PyErr_SetFromErrno (PyExc_OSError );
26682679    }
2669- 
26702680    Py_RETURN_NONE ;
26712681#else 
2682+     // Windows implementation 
26722683    assert (pSetThreadDescription  !=  NULL );
26732684
26742685    Py_ssize_t  len ;
@@ -2678,7 +2689,7 @@ _thread_set_name_impl(PyObject *module, PyObject *name_obj)
26782689    }
26792690
26802691    if  (len  >  _PYTHREAD_NAME_MAXLEN ) {
2681-         /*  Truncate the name */  
2692+         //  Truncate the name 
26822693        Py_UCS4  ch  =  name [_PYTHREAD_NAME_MAXLEN - 1 ];
26832694        if  (Py_UNICODE_IS_HIGH_SURROGATE (ch )) {
26842695            name [_PYTHREAD_NAME_MAXLEN - 1 ] =  0 ;
@@ -2697,7 +2708,6 @@ _thread_set_name_impl(PyObject *module, PyObject *name_obj)
26972708    Py_RETURN_NONE ;
26982709#endif 
26992710}
2700- 
27012711#endif   // HAVE_PTHREAD_SETNAME_NP || HAVE_PTHREAD_SET_NAME_NP || MS_WINDOWS 
27022712
27032713
0 commit comments