gh-138004: Fix setting a thread name on OpenIndiana (GH-138017)

Encode Solaris/Illumos thread names to ASCII, since
OpenIndiana does not support non-ASCII names.

Add tests for setting non-ASCII name for the main thread.

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
jadonduff 2025-09-02 11:26:25 -04:00 committed by GitHub
parent 8d5c3341c5
commit c19db1d2b8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 19 additions and 6 deletions

View file

@ -2281,6 +2281,9 @@ class MiscTestCase(unittest.TestCase):
@unittest.skipUnless(hasattr(_thread, 'set_name'), "missing _thread.set_name") @unittest.skipUnless(hasattr(_thread, 'set_name'), "missing _thread.set_name")
@unittest.skipUnless(hasattr(_thread, '_get_name'), "missing _thread._get_name") @unittest.skipUnless(hasattr(_thread, '_get_name'), "missing _thread._get_name")
def test_set_name(self): def test_set_name(self):
# Ensure main thread name is restored after test
self.addCleanup(_thread.set_name, _thread._get_name())
# set_name() limit in bytes # set_name() limit in bytes
truncate = getattr(_thread, "_NAME_MAXLEN", None) truncate = getattr(_thread, "_NAME_MAXLEN", None)
limit = truncate or 100 limit = truncate or 100
@ -2320,7 +2323,8 @@ class MiscTestCase(unittest.TestCase):
tests.append(os_helper.TESTFN_UNENCODABLE) tests.append(os_helper.TESTFN_UNENCODABLE)
if sys.platform.startswith("sunos"): if sys.platform.startswith("sunos"):
encoding = "utf-8" # Use ASCII encoding on Solaris/Illumos/OpenIndiana
encoding = "ascii"
else: else:
encoding = sys.getfilesystemencoding() encoding = sys.getfilesystemencoding()
@ -2336,7 +2340,7 @@ class MiscTestCase(unittest.TestCase):
if truncate is not None: if truncate is not None:
encoded = encoded[:truncate] encoded = encoded[:truncate]
if sys.platform.startswith("sunos"): if sys.platform.startswith("sunos"):
expected = encoded.decode("utf-8", "surrogateescape") expected = encoded.decode("ascii", "surrogateescape")
else: else:
expected = os.fsdecode(encoded) expected = os.fsdecode(encoded)
else: else:
@ -2355,7 +2359,11 @@ class MiscTestCase(unittest.TestCase):
if '\0' in expected: if '\0' in expected:
expected = expected.split('\0', 1)[0] expected = expected.split('\0', 1)[0]
with self.subTest(name=name, expected=expected): with self.subTest(name=name, expected=expected, thread="main"):
_thread.set_name(name)
self.assertEqual(_thread._get_name(), expected)
with self.subTest(name=name, expected=expected, thread="worker"):
work_name = None work_name = None
thread = threading.Thread(target=work, name=name) thread = threading.Thread(target=work, name=name)
thread.start() thread.start()

View file

@ -483,6 +483,7 @@ Weilin Du
John DuBois John DuBois
Paul Dubois Paul Dubois
Jacques Ducasse Jacques Ducasse
Jadon Duff
Andrei Dorian Duma Andrei Dorian Duma
Graham Dumpleton Graham Dumpleton
Quinn Dunkan Quinn Dunkan

View file

@ -0,0 +1 @@
On Solaris/Illumos platforms, thread names are now encoded as ASCII to avoid errors on systems (e.g. OpenIndiana) that don't support non-ASCII names.

View file

@ -2523,7 +2523,9 @@ _thread__get_name_impl(PyObject *module)
} }
#ifdef __sun #ifdef __sun
return PyUnicode_DecodeUTF8(name, strlen(name), "surrogateescape"); // gh-138004: Decode Solaris/Illumos (e.g. OpenIndiana) thread names
// from ASCII, since OpenIndiana only supports ASCII names.
return PyUnicode_DecodeASCII(name, strlen(name), "surrogateescape");
#else #else
return PyUnicode_DecodeFSDefault(name); return PyUnicode_DecodeFSDefault(name);
#endif #endif
@ -2561,8 +2563,9 @@ _thread_set_name_impl(PyObject *module, PyObject *name_obj)
{ {
#ifndef MS_WINDOWS #ifndef MS_WINDOWS
#ifdef __sun #ifdef __sun
// Solaris always uses UTF-8 // gh-138004: Encode Solaris/Illumos thread names to ASCII,
const char *encoding = "utf-8"; // since OpenIndiana does not support non-ASCII names.
const char *encoding = "ascii";
#else #else
// Encode the thread name to the filesystem encoding using the "replace" // Encode the thread name to the filesystem encoding using the "replace"
// error handler // error handler