mirror of
https://github.com/python/cpython.git
synced 2025-07-24 03:35:53 +00:00
Issue #11223: Replace threading._info() by sys.thread_info
This commit is contained in:
parent
fab6c70770
commit
d5c355ccc7
13 changed files with 119 additions and 108 deletions
|
@ -961,6 +961,35 @@ always available.
|
||||||
to a console and Python apps started with :program:`pythonw`.
|
to a console and Python apps started with :program:`pythonw`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: thread_info
|
||||||
|
|
||||||
|
A :term:`struct sequence` holding information about the thread
|
||||||
|
implementation.
|
||||||
|
|
||||||
|
+------------------+---------------------------------------------------------+
|
||||||
|
| Attribute | Explanation |
|
||||||
|
+==================+=========================================================+
|
||||||
|
| :const:`name` | Name of the thread implementation: |
|
||||||
|
| | |
|
||||||
|
| | * ``'nt'``: Windows threads |
|
||||||
|
| | * ``'os2'``: OS/2 threads |
|
||||||
|
| | * ``'pthread'``: POSIX threads |
|
||||||
|
| | * ``'solaris'``: Solaris threads |
|
||||||
|
+------------------+---------------------------------------------------------+
|
||||||
|
| :const:`lock` | Name of the lock implementation: |
|
||||||
|
| | |
|
||||||
|
| | * ``'semaphore'``: a lock uses a semaphore |
|
||||||
|
| | * ``'mutex+cond'``: a lock uses a mutex |
|
||||||
|
| | and a condition variable |
|
||||||
|
| | * ``None`` if this information is unknown |
|
||||||
|
+------------------+---------------------------------------------------------+
|
||||||
|
| :const:`version` | Name and version of the thread library. It is a string, |
|
||||||
|
| | or ``None`` if these informations are unknown. |
|
||||||
|
+------------------+---------------------------------------------------------+
|
||||||
|
|
||||||
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
|
||||||
.. data:: tracebacklimit
|
.. data:: tracebacklimit
|
||||||
|
|
||||||
When this variable is set to an integer value, it determines the maximum number
|
When this variable is set to an integer value, it determines the maximum number
|
||||||
|
|
|
@ -175,30 +175,6 @@ This module defines the following functions and objects:
|
||||||
Availability: Windows, systems with POSIX threads.
|
Availability: Windows, systems with POSIX threads.
|
||||||
|
|
||||||
|
|
||||||
.. function:: _info()
|
|
||||||
|
|
||||||
Return a dictionary with informations about the thread implementation.
|
|
||||||
The ``'name'`` key gives the name of the thread implementation (string):
|
|
||||||
|
|
||||||
* ``'nt'``: Windows threads
|
|
||||||
* ``'os2'``: OS/2 threads
|
|
||||||
* ``'pthread'``: POSIX threads
|
|
||||||
* ``'solaris'``: Solaris threads
|
|
||||||
|
|
||||||
POSIX threads have two more keys:
|
|
||||||
|
|
||||||
* ``'lock_implementation'`` (string): name of the lock
|
|
||||||
implementation
|
|
||||||
|
|
||||||
* ``'semaphore'``: a lock uses a semaphore
|
|
||||||
* ``'mutex+cond'``: a lock uses a mutex and a condition variable
|
|
||||||
|
|
||||||
* ``'pthread_version'`` (string, optional): name and version of the pthread
|
|
||||||
library
|
|
||||||
|
|
||||||
.. versionadded:: 3.3
|
|
||||||
|
|
||||||
|
|
||||||
This module also defines the following constant:
|
This module also defines the following constant:
|
||||||
|
|
||||||
.. data:: TIMEOUT_MAX
|
.. data:: TIMEOUT_MAX
|
||||||
|
|
|
@ -112,11 +112,11 @@ connection when done::
|
||||||
|
|
||||||
(Contributed by Giampaolo Rodolà in :issue:`9795`)
|
(Contributed by Giampaolo Rodolà in :issue:`9795`)
|
||||||
|
|
||||||
threading
|
sys
|
||||||
---------
|
---
|
||||||
|
|
||||||
* The :mod:`threading` module has a new :func:`~threading._info` function which
|
* The :mod:`sys` module has a new :func:`~sys.thread_info` :term:`struct
|
||||||
provides informations about the thread implementation.
|
sequence` holding informations about the thread implementation.
|
||||||
|
|
||||||
(:issue:`11223`)
|
(:issue:`11223`)
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ PyAPI_FUNC(void) PyThread_release_lock(PyThread_type_lock);
|
||||||
PyAPI_FUNC(size_t) PyThread_get_stacksize(void);
|
PyAPI_FUNC(size_t) PyThread_get_stacksize(void);
|
||||||
PyAPI_FUNC(int) PyThread_set_stacksize(size_t);
|
PyAPI_FUNC(int) PyThread_set_stacksize(size_t);
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject*) _PyThread_Info(void);
|
PyAPI_FUNC(PyObject*) PyThread_GetInfo(void);
|
||||||
|
|
||||||
/* Thread Local Storage (TLS) API */
|
/* Thread Local Storage (TLS) API */
|
||||||
PyAPI_FUNC(int) PyThread_create_key(void);
|
PyAPI_FUNC(int) PyThread_create_key(void);
|
||||||
|
|
|
@ -149,6 +149,3 @@ def interrupt_main():
|
||||||
else:
|
else:
|
||||||
global _interrupt
|
global _interrupt
|
||||||
_interrupt = True
|
_interrupt = True
|
||||||
|
|
||||||
def info():
|
|
||||||
return {'name': 'dummy'}
|
|
||||||
|
|
|
@ -27,15 +27,10 @@ except ImportError:
|
||||||
# and unmaintained) linuxthreads threading library. There's an issue
|
# and unmaintained) linuxthreads threading library. There's an issue
|
||||||
# when combining linuxthreads with a failed execv call: see
|
# when combining linuxthreads with a failed execv call: see
|
||||||
# http://bugs.python.org/issue4970.
|
# http://bugs.python.org/issue4970.
|
||||||
USING_LINUXTHREADS = False
|
if hasattr(sys, 'thread_info') and sys.thread_info.version:
|
||||||
if threading:
|
USING_LINUXTHREADS = sys.thread_info.version.startswith("linuxthreads")
|
||||||
info = threading._info()
|
else:
|
||||||
try:
|
USING_LINUXTHREADS = False
|
||||||
pthread_version = info['pthread_version']
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
USING_LINUXTHREADS = pthread_version.startswith("linuxthreads")
|
|
||||||
|
|
||||||
# Tests creating TESTFN
|
# Tests creating TESTFN
|
||||||
class FileTests(unittest.TestCase):
|
class FileTests(unittest.TestCase):
|
||||||
|
|
|
@ -474,6 +474,14 @@ class SysModuleTest(unittest.TestCase):
|
||||||
if not sys.platform.startswith('win'):
|
if not sys.platform.startswith('win'):
|
||||||
self.assertIsInstance(sys.abiflags, str)
|
self.assertIsInstance(sys.abiflags, str)
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(sys, 'thread_info'),
|
||||||
|
'Threading required for this test.')
|
||||||
|
def test_thread_info(self):
|
||||||
|
info = sys.thread_info
|
||||||
|
self.assertTrue(len(info), 3)
|
||||||
|
self.assertIn(info.name, ('nt', 'os2', 'pthread', 'solaris', None))
|
||||||
|
self.assertIn(info.lock, ('semaphore', 'mutex+cond', None))
|
||||||
|
|
||||||
def test_43581(self):
|
def test_43581(self):
|
||||||
# Can't use sys.stdout, as this is a StringIO object when
|
# Can't use sys.stdout, as this is a StringIO object when
|
||||||
# the test runs under regrtest.
|
# the test runs under regrtest.
|
||||||
|
|
|
@ -719,16 +719,6 @@ class BarrierTests(lock_tests.BarrierTests):
|
||||||
barriertype = staticmethod(threading.Barrier)
|
barriertype = staticmethod(threading.Barrier)
|
||||||
|
|
||||||
|
|
||||||
class MiscTests(unittest.TestCase):
|
|
||||||
def test_info(self):
|
|
||||||
info = threading._info()
|
|
||||||
self.assertIn(info['name'],
|
|
||||||
'nt os2 pthread solaris'.split())
|
|
||||||
if info['name'] == 'pthread':
|
|
||||||
self.assertIn(info['lock_implementation'],
|
|
||||||
('semaphore', 'mutex+cond'))
|
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
test.support.run_unittest(LockTests, PyRLockTests, CRLockTests, EventTests,
|
test.support.run_unittest(LockTests, PyRLockTests, CRLockTests, EventTests,
|
||||||
ConditionAsRLockTests, ConditionTests,
|
ConditionAsRLockTests, ConditionTests,
|
||||||
|
@ -736,7 +726,7 @@ def test_main():
|
||||||
ThreadTests,
|
ThreadTests,
|
||||||
ThreadJoinOnShutdown,
|
ThreadJoinOnShutdown,
|
||||||
ThreadingExceptionTests,
|
ThreadingExceptionTests,
|
||||||
BarrierTests, MiscTests,
|
BarrierTests,
|
||||||
)
|
)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -14,9 +14,8 @@ if sys.platform[:3] in ('win', 'os2') or sys.platform=='riscos':
|
||||||
process_pid = os.getpid()
|
process_pid = os.getpid()
|
||||||
signalled_all=thread.allocate_lock()
|
signalled_all=thread.allocate_lock()
|
||||||
|
|
||||||
info = thread.info()
|
USING_PTHREAD_COND = (sys.thread_info.name == 'pthread'
|
||||||
USING_PTHREAD_COND = (info['name'] == 'pthread'
|
and sys.thread_info.lock == 'mutex+cond')
|
||||||
and info['lock_implementation'] == 'mutex+cond')
|
|
||||||
|
|
||||||
def registerSignals(for_usr1, for_usr2, for_alrm):
|
def registerSignals(for_usr1, for_usr2, for_alrm):
|
||||||
usr1 = signal.signal(signal.SIGUSR1, for_usr1)
|
usr1 = signal.signal(signal.SIGUSR1, for_usr1)
|
||||||
|
|
|
@ -19,7 +19,7 @@ from collections import deque
|
||||||
|
|
||||||
__all__ = ['active_count', 'Condition', 'current_thread', 'enumerate', 'Event',
|
__all__ = ['active_count', 'Condition', 'current_thread', 'enumerate', 'Event',
|
||||||
'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', 'Barrier',
|
'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', 'Barrier',
|
||||||
'Timer', 'setprofile', 'settrace', 'local', 'stack_size', '_info']
|
'Timer', 'setprofile', 'settrace', 'local', 'stack_size']
|
||||||
|
|
||||||
# Rename some stuff so "from threading import *" is safe
|
# Rename some stuff so "from threading import *" is safe
|
||||||
_start_new_thread = _thread.start_new_thread
|
_start_new_thread = _thread.start_new_thread
|
||||||
|
@ -31,7 +31,6 @@ try:
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
_CRLock = None
|
_CRLock = None
|
||||||
TIMEOUT_MAX = _thread.TIMEOUT_MAX
|
TIMEOUT_MAX = _thread.TIMEOUT_MAX
|
||||||
_info = _thread.info
|
|
||||||
del _thread
|
del _thread
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1227,17 +1227,6 @@ requiring allocation in multiples of the system memory page size\n\
|
||||||
(4kB pages are common; using multiples of 4096 for the stack size is\n\
|
(4kB pages are common; using multiples of 4096 for the stack size is\n\
|
||||||
the suggested approach in the absence of more specific information).");
|
the suggested approach in the absence of more specific information).");
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
thread_info(PyObject *self)
|
|
||||||
{
|
|
||||||
return _PyThread_Info();
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(thread_info_doc,
|
|
||||||
"info() -> dict\n\
|
|
||||||
\n\
|
|
||||||
Informations about the thread implementation.");
|
|
||||||
|
|
||||||
static PyMethodDef thread_methods[] = {
|
static PyMethodDef thread_methods[] = {
|
||||||
{"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
|
{"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
|
||||||
METH_VARARGS, start_new_doc},
|
METH_VARARGS, start_new_doc},
|
||||||
|
@ -1259,8 +1248,6 @@ static PyMethodDef thread_methods[] = {
|
||||||
METH_NOARGS, _count_doc},
|
METH_NOARGS, _count_doc},
|
||||||
{"stack_size", (PyCFunction)thread_stack_size,
|
{"stack_size", (PyCFunction)thread_stack_size,
|
||||||
METH_VARARGS, stack_size_doc},
|
METH_VARARGS, stack_size_doc},
|
||||||
{"info", (PyCFunction)thread_info,
|
|
||||||
METH_NOARGS, thread_info_doc},
|
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ Data members:
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "code.h"
|
#include "code.h"
|
||||||
#include "frameobject.h"
|
#include "frameobject.h"
|
||||||
|
#include "pythread.h"
|
||||||
|
|
||||||
#include "osdefs.h"
|
#include "osdefs.h"
|
||||||
|
|
||||||
|
@ -1251,20 +1252,21 @@ PyDoc_STR(
|
||||||
"\n\
|
"\n\
|
||||||
Static objects:\n\
|
Static objects:\n\
|
||||||
\n\
|
\n\
|
||||||
float_info -- a dict with information about the float implementation.\n\
|
builtin_module_names -- tuple of module names built into this interpreter\n\
|
||||||
|
copyright -- copyright notice pertaining to this interpreter\n\
|
||||||
|
exec_prefix -- prefix used to find the machine-specific Python library\n\
|
||||||
|
executable -- pathname of this Python interpreter\n\
|
||||||
|
float_info -- a struct sequence with information about the float implementation.\n\
|
||||||
|
float_repr_style -- string indicating the style of repr() output for floats\n\
|
||||||
|
hexversion -- version information encoded as a single integer\n\
|
||||||
int_info -- a struct sequence with information about the int implementation.\n\
|
int_info -- a struct sequence with information about the int implementation.\n\
|
||||||
maxsize -- the largest supported length of containers.\n\
|
maxsize -- the largest supported length of containers.\n\
|
||||||
maxunicode -- the largest supported character\n\
|
maxunicode -- the largest supported character\n\
|
||||||
builtin_module_names -- tuple of module names built into this interpreter\n\
|
platform -- platform identifier\n\
|
||||||
|
prefix -- prefix used to find the Python library\n\
|
||||||
|
thread_info -- a struct sequence with information about the thread implementation.\n\
|
||||||
version -- the version of this interpreter as a string\n\
|
version -- the version of this interpreter as a string\n\
|
||||||
version_info -- version information as a named tuple\n\
|
version_info -- version information as a named tuple\n\
|
||||||
hexversion -- version information encoded as a single integer\n\
|
|
||||||
copyright -- copyright notice pertaining to this interpreter\n\
|
|
||||||
platform -- platform identifier\n\
|
|
||||||
executable -- pathname of this Python interpreter\n\
|
|
||||||
prefix -- prefix used to find the Python library\n\
|
|
||||||
exec_prefix -- prefix used to find the machine-specific Python library\n\
|
|
||||||
float_repr_style -- string indicating the style of repr() output for floats\n\
|
|
||||||
"
|
"
|
||||||
)
|
)
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
@ -1611,6 +1613,10 @@ _PySys_Init(void)
|
||||||
PyUnicode_FromString("legacy"));
|
PyUnicode_FromString("legacy"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_THREAD
|
||||||
|
SET_SYS_FROM_STRING("thread_info", PyThread_GetInfo());
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef SET_SYS_FROM_STRING
|
#undef SET_SYS_FROM_STRING
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef _POSIX_THREADS
|
#ifndef _POSIX_THREADS
|
||||||
/* This means pthreads are not implemented in libc headers, hence the macro
|
/* This means pthreads are not implemented in libc headers, hence the macro
|
||||||
not present in unistd.h. But they still can be implemented as an external
|
not present in unistd.h. But they still can be implemented as an external
|
||||||
|
@ -415,26 +414,51 @@ PyThread_ReInitTLS(void)
|
||||||
|
|
||||||
#endif /* Py_HAVE_NATIVE_TLS */
|
#endif /* Py_HAVE_NATIVE_TLS */
|
||||||
|
|
||||||
|
PyDoc_STRVAR(threadinfo__doc__,
|
||||||
|
"sys.thread_info\n\
|
||||||
|
\n\
|
||||||
|
A struct sequence holding information about the thread implementation.");
|
||||||
|
|
||||||
|
static PyStructSequence_Field threadinfo_fields[] = {
|
||||||
|
{"name", "name of the thread implementation"},
|
||||||
|
{"lock", "name of the lock implementation"},
|
||||||
|
{"version", "name and version of the thread library"},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyStructSequence_Desc threadinfo_desc = {
|
||||||
|
"sys.thread_info", /* name */
|
||||||
|
threadinfo__doc__, /* doc */
|
||||||
|
threadinfo_fields, /* fields */
|
||||||
|
3
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyTypeObject ThreadInfoType;
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
_PyThread_Info(void)
|
PyThread_GetInfo(void)
|
||||||
{
|
{
|
||||||
PyObject *info, *value;
|
PyObject *threadinfo, *value;
|
||||||
int ret;
|
int pos = 0;
|
||||||
#if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \
|
#if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \
|
||||||
&& defined(_CS_GNU_LIBPTHREAD_VERSION))
|
&& defined(_CS_GNU_LIBPTHREAD_VERSION))
|
||||||
char buffer[255];
|
char buffer[255];
|
||||||
int len;
|
int len;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
info = PyDict_New();
|
if (ThreadInfoType.tp_name == 0)
|
||||||
if (info == NULL)
|
PyStructSequence_InitType(&ThreadInfoType, &threadinfo_desc);
|
||||||
|
|
||||||
|
threadinfo = PyStructSequence_New(&ThreadInfoType);
|
||||||
|
if (threadinfo == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
value = PyUnicode_FromString(PYTHREAD_NAME);
|
value = PyUnicode_FromString(PYTHREAD_NAME);
|
||||||
ret = PyDict_SetItemString(info, "name", value);
|
if (value == NULL) {
|
||||||
Py_DECREF(value);
|
Py_DECREF(threadinfo);
|
||||||
if (ret)
|
return NULL;
|
||||||
goto error;
|
}
|
||||||
|
PyStructSequence_SET_ITEM(threadinfo, pos++, value);
|
||||||
|
|
||||||
#ifdef _POSIX_THREADS
|
#ifdef _POSIX_THREADS
|
||||||
#ifdef USE_SEMAPHORES
|
#ifdef USE_SEMAPHORES
|
||||||
|
@ -442,30 +466,31 @@ _PyThread_Info(void)
|
||||||
#else
|
#else
|
||||||
value = PyUnicode_FromString("mutex+cond");
|
value = PyUnicode_FromString("mutex+cond");
|
||||||
#endif
|
#endif
|
||||||
if (value == NULL)
|
if (value == NULL) {
|
||||||
|
Py_DECREF(threadinfo);
|
||||||
return NULL;
|
return NULL;
|
||||||
ret = PyDict_SetItemString(info, "lock_implementation", value);
|
}
|
||||||
Py_DECREF(value);
|
#else
|
||||||
if (ret)
|
Py_INCREF(Py_None);
|
||||||
goto error;
|
value = Py_None;
|
||||||
|
#endif
|
||||||
|
PyStructSequence_SET_ITEM(threadinfo, pos++, value);
|
||||||
|
|
||||||
#if defined(HAVE_CONFSTR) && defined(_CS_GNU_LIBPTHREAD_VERSION)
|
#if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \
|
||||||
|
&& defined(_CS_GNU_LIBPTHREAD_VERSION))
|
||||||
|
value = NULL;
|
||||||
len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
|
len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
|
||||||
if (0 < len && len < sizeof(buffer)) {
|
if (1 < len && len < sizeof(buffer)) {
|
||||||
value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
|
value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
goto error;
|
PyErr_Clear();
|
||||||
ret = PyDict_SetItemString(info, "pthread_version", value);
|
|
||||||
Py_DECREF(value);
|
|
||||||
if (ret)
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
if (value == NULL)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
{
|
||||||
|
Py_INCREF(Py_None);
|
||||||
return info;
|
value = Py_None;
|
||||||
|
}
|
||||||
error:
|
PyStructSequence_SET_ITEM(threadinfo, pos++, value);
|
||||||
Py_DECREF(info);
|
return threadinfo;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue