Skip to content

Commit 25085bf

Browse files
committed
encode ascii on solaris/openindiana
1 parent 508f24d commit 25085bf

File tree

1 file changed

+37
-95
lines changed

1 file changed

+37
-95
lines changed

Modules/_threadmodule.c

Lines changed: 37 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,6 @@
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-
670658
static void
671659
PyThreadHandleObject_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-
782763
static void
783764
lock_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-
10751049
static int
10761050
rlock_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
29322874
PyInit__thread(void)
29332875
{
29342876
return PyModuleDef_Init(&thread_module);
2935-
}
2877+
}

0 commit comments

Comments
 (0)