]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-112535: Add test on _Py_ThreadId() (#112709)
authorVictor Stinner <vstinner@python.org>
Mon, 4 Dec 2023 22:40:06 +0000 (23:40 +0100)
committerGitHub <noreply@github.com>
Mon, 4 Dec 2023 22:40:06 +0000 (22:40 +0000)
Add also test.support.Py_GIL_DISABLED constant.

Lib/test/support/__init__.py
Lib/test/test_capi/test_misc.py
Lib/test/test_cppext/__init__.py
Lib/test/test_importlib/test_windows.py
Lib/test/test_sys.py
Modules/_testinternalcapi.c

index 318a0599a75acd78ec373b3109982d726f86db62..c22d73c231b46e45dc5be16b45ae8c607c2ed609 100644 (file)
@@ -796,7 +796,8 @@ def check_cflags_pgo():
     return any(option in cflags_nodist for option in pgo_options)
 
 
-if sysconfig.get_config_var('Py_GIL_DISABLED'):
+Py_GIL_DISABLED = bool(sysconfig.get_config_var('Py_GIL_DISABLED'))
+if Py_GIL_DISABLED:
     _header = 'PHBBInP'
 else:
     _header = 'nP'
index 6cbf5d222038048e38118630488566e540f3ba18..3d86ae37190475e0894f350683e626a9f98200c3 100644 (file)
@@ -2854,5 +2854,60 @@ class TestUops(unittest.TestCase):
         self.assertIn("_FOR_ITER_TIER_TWO", uops)
 
 
+@unittest.skipUnless(support.Py_GIL_DISABLED, 'need Py_GIL_DISABLED')
+class TestPyThreadId(unittest.TestCase):
+    def test_py_thread_id(self):
+        # gh-112535: Test _Py_ThreadId(): make sure that thread identifiers
+        # in a few threads are unique
+        py_thread_id = _testinternalcapi.py_thread_id
+        short_sleep = 0.010
+
+        class GetThreadId(threading.Thread):
+            def __init__(self):
+                super().__init__()
+                self.get_lock = threading.Lock()
+                self.get_lock.acquire()
+                self.started_lock = threading.Event()
+                self.py_tid = None
+
+            def run(self):
+                self.started_lock.set()
+                self.get_lock.acquire()
+                self.py_tid = py_thread_id()
+                time.sleep(short_sleep)
+                self.py_tid2 = py_thread_id()
+
+        nthread = 5
+        threads = [GetThreadId() for _ in range(nthread)]
+
+        # first make run sure that all threads are running
+        for thread in threads:
+            thread.start()
+        for thread in threads:
+            thread.started_lock.wait()
+
+        # call _Py_ThreadId() in the main thread
+        py_thread_ids = [py_thread_id()]
+
+        # now call _Py_ThreadId() in each thread
+        for thread in threads:
+            thread.get_lock.release()
+
+        # call _Py_ThreadId() in each thread and wait until threads complete
+        for thread in threads:
+            thread.join()
+            py_thread_ids.append(thread.py_tid)
+            # _PyThread_Id() should not change for a given thread.
+            # For example, it should remain the same after a short sleep.
+            self.assertEqual(thread.py_tid2, thread.py_tid)
+
+        # make sure that all _Py_ThreadId() are unique
+        for tid in py_thread_ids:
+            self.assertIsInstance(tid, int)
+            self.assertGreater(tid, 0)
+        self.assertEqual(len(set(py_thread_ids)), len(py_thread_ids),
+                         py_thread_ids)
+
+
 if __name__ == "__main__":
     unittest.main()
index 299a16ada2e32efab0212bbe932e3a80e97522e0..c6039bd17b066242f0541f6abcc5445efee4e961 100644 (file)
@@ -2,7 +2,6 @@
 # compatible with C++ and does not emit C++ compiler warnings.
 import os.path
 import shutil
-import sys
 import unittest
 import subprocess
 import sysconfig
@@ -15,7 +14,7 @@ SETUP = os.path.join(os.path.dirname(__file__), 'setup.py')
 
 # gh-110119: pip does not currently support 't' in the ABI flag use by
 # --disable-gil builds. Once it does, we can remove this skip.
-@unittest.skipIf(sysconfig.get_config_var('Py_GIL_DISABLED') == 1,
+@unittest.skipIf(support.Py_GIL_DISABLED,
                  'test does not work with --disable-gil')
 @support.requires_subprocess()
 class TestCPPExt(unittest.TestCase):
index d25133240b1afdbabc503da1db2edf427b05f2c9..8a9a8fffcd10d49b01f915933ff8d10daa3a0a8e 100644 (file)
@@ -4,8 +4,8 @@ machinery = test_util.import_importlib('importlib.machinery')
 import os
 import re
 import sys
-import sysconfig
 import unittest
+from test import support
 from test.support import import_helper
 from contextlib import contextmanager
 from test.test_importlib.util import temp_module
@@ -112,7 +112,7 @@ class WindowsRegistryFinderTests:
 class WindowsExtensionSuffixTests:
     def test_tagged_suffix(self):
         suffixes = self.machinery.EXTENSION_SUFFIXES
-        abi_flags = "t" if sysconfig.get_config_var("Py_GIL_DISABLED") else ""
+        abi_flags = "t" if support.Py_GIL_DISABLED else ""
         ver = sys.version_info
         platform = re.sub('[^a-zA-Z0-9]', '_', get_platform())
         expected_tag = f".cp{ver.major}{ver.minor}{abi_flags}-{platform}.pyd"
index 8c2c1a40f74bf245a9a5557ff8b0ea476c3343d5..db5ba16c4d97399a19789c88f93b9b44a97d1717 100644 (file)
@@ -1224,9 +1224,7 @@ class SysModuleTest(unittest.TestCase):
     @test.support.cpython_only
     @unittest.skipUnless(hasattr(sys, 'abiflags'), 'need sys.abiflags')
     def test_disable_gil_abi(self):
-        abi_threaded = 't' in sys.abiflags
-        py_gil_disabled = (sysconfig.get_config_var('Py_GIL_DISABLED') == 1)
-        self.assertEqual(py_gil_disabled, abi_threaded)
+        self.assertEqual('t' in sys.abiflags, support.Py_GIL_DISABLED)
 
 
 @test.support.cpython_only
index 4607a3faf17f74c5b1be74875b0d6c86bed951ff..ba7653f2d9c7aa750c5d386c5bc18784de5e730b 100644 (file)
@@ -1625,6 +1625,17 @@ get_type_module_name(PyObject *self, PyObject *type)
 }
 
 
+#ifdef Py_GIL_DISABLED
+static PyObject *
+get_py_thread_id(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    uintptr_t tid = _Py_ThreadId();
+    Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(tid));
+    return PyLong_FromUnsignedLongLong(tid);
+}
+#endif
+
+
 static PyMethodDef module_functions[] = {
     {"get_configs", get_configs, METH_NOARGS},
     {"get_recursion_depth", get_recursion_depth, METH_NOARGS},
@@ -1688,6 +1699,9 @@ static PyMethodDef module_functions[] = {
     {"restore_crossinterp_data", restore_crossinterp_data,       METH_VARARGS},
     _TESTINTERNALCAPI_TEST_LONG_NUMBITS_METHODDEF
     {"get_type_module_name",    get_type_module_name,            METH_O},
+#ifdef Py_GIL_DISABLED
+    {"py_thread_id", get_py_thread_id, METH_NOARGS},
+#endif
     {NULL, NULL} /* sentinel */
 };