1717#ifdef HAVE_SIGNAL_H
1818# include <signal.h> // SIGINT
1919#endif
20- #ifdef HAVE_PTHREAD_H
21- # include <pthread.h>
22- #endif
23- #include <errno.h>
24- #include <string.h>
2520
2621// ThreadError is just an alias to PyExc_RuntimeError
2722#define ThreadError PyExc_RuntimeError
@@ -660,13 +655,6 @@ PyThreadHandleObject_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
660655 return (PyObject * )PyThreadHandleObject_new (type );
661656}
662657
663- static int
664- PyThreadHandleObject_traverse (PyObject * self , visitproc visit , void * arg )
665- {
666- Py_VISIT (Py_TYPE (self ));
667- return 0 ;
668- }
669-
670658static void
671659PyThreadHandleObject_dealloc (PyObject * op )
672660{
@@ -756,7 +744,7 @@ static PyType_Slot ThreadHandle_Type_slots[] = {
756744 {Py_tp_dealloc , PyThreadHandleObject_dealloc },
757745 {Py_tp_repr , PyThreadHandleObject_repr },
758746 {Py_tp_getset , ThreadHandle_getsetlist },
759- {Py_tp_traverse , PyThreadHandleObject_traverse },
747+ {Py_tp_traverse , _PyObject_VisitType },
760748 {Py_tp_methods , ThreadHandle_methods },
761749 {Py_tp_new , PyThreadHandleObject_tp_new },
762750 {0 , 0 }
@@ -772,13 +760,6 @@ static PyType_Spec ThreadHandle_Type_spec = {
772760
773761/* Lock objects */
774762
775- static int
776- lock_traverse (PyObject * self , visitproc visit , void * arg )
777- {
778- Py_VISIT (Py_TYPE (self ));
779- return 0 ;
780- }
781-
782763static void
783764lock_dealloc (PyObject * self )
784765{
@@ -1050,7 +1031,7 @@ static PyType_Slot lock_type_slots[] = {
10501031 {Py_tp_repr , lock_repr },
10511032 {Py_tp_doc , (void * )lock_doc },
10521033 {Py_tp_methods , lock_methods },
1053- {Py_tp_traverse , lock_traverse },
1034+ {Py_tp_traverse , _PyObject_VisitType },
10541035 {Py_tp_new , lock_new },
10551036 {0 , 0 }
10561037};
@@ -1065,13 +1046,6 @@ static PyType_Spec lock_type_spec = {
10651046
10661047/* Recursive lock objects */
10671048
1068- static int
1069- rlock_traverse (PyObject * self , visitproc visit , void * arg )
1070- {
1071- Py_VISIT (Py_TYPE (self ));
1072- return 0 ;
1073- }
1074-
10751049static int
10761050rlock_locked_impl (rlockobject * self )
10771051{
@@ -1364,7 +1338,7 @@ static PyType_Slot rlock_type_slots[] = {
13641338 {Py_tp_methods , rlock_methods },
13651339 {Py_tp_alloc , PyType_GenericAlloc },
13661340 {Py_tp_new , rlock_new },
1367- {Py_tp_traverse , rlock_traverse },
1341+ {Py_tp_traverse , _PyObject_VisitType },
13681342 {0 , 0 },
13691343};
13701344
@@ -2522,58 +2496,6 @@ of the main interpreter.");
25222496# include <pthread_np.h>
25232497#endif
25242498
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- */
2531- static int
2532- set_encoded_thread_name (PyObject * name_obj , const char * encoding )
2533- {
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 );
2555- int rc = 0 ;
2556-
2557- #ifdef __APPLE__
2558- rc = pthread_setname_np (name );
2559- #elif defined(__NetBSD__ )
2560- pthread_t thread = pthread_self ();
2561- rc = pthread_setname_np (thread , "%s" , (void * )name );
2562- #elif defined(HAVE_PTHREAD_SETNAME_NP )
2563- pthread_t thread = pthread_self ();
2564- rc = pthread_setname_np (thread , name );
2565- #elif defined(HAVE_PTHREAD_SET_NAME_NP )
2566- pthread_t thread = pthread_self ();
2567- pthread_set_name_np (thread , name );
2568- rc = 0 ; /* that API returns void */
2569- #else
2570- rc = 0 ; /* no-op if platform unsupported */
2571- #endif
2572-
2573- Py_DECREF (name_encoded );
2574- return rc ;
2575- }
2576-
25772499#if defined(HAVE_PTHREAD_GETNAME_NP ) || defined(HAVE_PTHREAD_GET_NAME_NP ) || defined(MS_WINDOWS )
25782500/*[clinic input]
25792501_thread._get_name
@@ -2601,7 +2523,8 @@ _thread__get_name_impl(PyObject *module)
26012523 }
26022524
26032525#ifdef __sun
2604- return PyUnicode_DecodeUTF8 (name , strlen (name ), "surrogateescape" );
2526+ // Decode Solaris/Illumos (e.g. OpenIndiana) thread names as ASCII with "replace" to avoid decoding errors.
2527+ return PyUnicode_DecodeASCII (name , strlen (name ), "replace" );
26052528#else
26062529 return PyUnicode_DecodeFSDefault (name );
26072530#endif
@@ -2639,30 +2562,49 @@ _thread_set_name_impl(PyObject *module, PyObject *name_obj)
26392562{
26402563#ifndef MS_WINDOWS
26412564#ifdef __sun
2642- // Solaris always uses UTF-8
2643- const char * encoding = "utf-8 " ;
2565+ // Decode Solaris/Illumos (e.g. OpenIndiana) thread names as ASCII to avoid decoding errors.
2566+ const char * encoding = "ascii " ;
26442567#else
26452568 // Encode the thread name to the filesystem encoding using the "replace"
26462569 // error handler
26472570 PyInterpreterState * interp = _PyInterpreterState_GET ();
26482571 const char * encoding = interp -> unicode .fs_codec .encoding ;
26492572#endif
2650-
2651- int rc = set_encoded_thread_name (name_obj , encoding );
2652- /* Confirm a Python exception was set by the helper.
2653- If not, convert to a runtime error (defensive). */
2654- if (rc == -1 && PyErr_Occurred ()) {
2573+ PyObject * name_encoded ;
2574+ name_encoded = PyUnicode_AsEncodedString (name_obj , encoding , "replace" );
2575+ if (name_encoded == NULL ) {
26552576 return NULL ;
26562577 }
26572578
2658- /* If native API refused (EINVAL) and we didn't try ASCII, retry with ASCII. */
2659- if (rc == EINVAL && strcmp (encoding , "ascii" ) != 0 ) {
2660- rc = set_encoded_thread_name (name_obj , "ascii" );
2661- if (rc == -1 && PyErr_Occurred ()) {
2579+ #ifdef _PYTHREAD_NAME_MAXLEN
2580+ // Truncate to _PYTHREAD_NAME_MAXLEN bytes + the NUL byte if needed
2581+ if (PyBytes_GET_SIZE (name_encoded ) > _PYTHREAD_NAME_MAXLEN ) {
2582+ PyObject * truncated ;
2583+ truncated = PyBytes_FromStringAndSize (PyBytes_AS_STRING (name_encoded ),
2584+ _PYTHREAD_NAME_MAXLEN );
2585+ if (truncated == NULL ) {
2586+ Py_DECREF (name_encoded );
26622587 return NULL ;
26632588 }
2664- /* fall through to raise errno below */
2589+ Py_SETREF ( name_encoded , truncated );
26652590 }
2591+ #endif
2592+
2593+ const char * name = PyBytes_AS_STRING (name_encoded );
2594+ #ifdef __APPLE__
2595+ int rc = pthread_setname_np (name );
2596+ #elif defined(__NetBSD__ )
2597+ pthread_t thread = pthread_self ();
2598+ int rc = pthread_setname_np (thread , "%s" , (void * )name );
2599+ #elif defined(HAVE_PTHREAD_SETNAME_NP )
2600+ pthread_t thread = pthread_self ();
2601+ int rc = pthread_setname_np (thread , name );
2602+ #else /* defined(HAVE_PTHREAD_SET_NAME_NP) */
2603+ pthread_t thread = pthread_self ();
2604+ int rc = 0 ; /* pthread_set_name_np() returns void */
2605+ pthread_set_name_np (thread , name );
2606+ #endif
2607+ Py_DECREF (name_encoded );
26662608 if (rc ) {
26672609 errno = rc ;
26682610 return PyErr_SetFromErrno (PyExc_OSError );
@@ -2932,4 +2874,4 @@ PyMODINIT_FUNC
29322874PyInit__thread (void )
29332875{
29342876 return PyModuleDef_Init (& thread_module );
2935- }
2877+ }
0 commit comments