summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_sys.py22
-rw-r--r--Misc/NEWS13
-rw-r--r--Python/pystate.c95
3 files changed, 78 insertions, 52 deletions
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index bb86c88..9d4bbe7 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -239,6 +239,19 @@ class SysModuleTest(unittest.TestCase):
# sys._current_frames() is a CPython-only gimmick.
def test_current_frames(self):
+ have_threads = True
+ try:
+ import thread
+ except ImportError:
+ have_threads = False
+
+ if have_threads:
+ self.current_frames_with_threads()
+ else:
+ self.current_frames_without_threads()
+
+ # Test sys._current_frames() in a WITH_THREADS build.
+ def current_frames_with_threads(self):
import threading, thread
import traceback
@@ -298,6 +311,15 @@ class SysModuleTest(unittest.TestCase):
leave_g.set()
t.join()
+ # Test sys._current_frames() when thread support doesn't exist.
+ def current_frames_without_threads(self):
+ # Not much happens here: there is only one thread, with artificial
+ # "thread id" 0.
+ d = sys._current_frames()
+ self.assertEqual(len(d), 1)
+ self.assert_(0 in d)
+ self.assert_(d[0] is sys._getframe())
+
def test_attributes(self):
self.assert_(isinstance(sys.api_version, int))
self.assert_(isinstance(sys.argv, list))
diff --git a/Misc/NEWS b/Misc/NEWS
index 9fa594e..7339db2 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -24,6 +24,11 @@ Core and builtins
again. Fixing this problem required changing the .pyc magic number.
This means that .pyc files generated before 2.5c1 will be regenerated.
+- Bug #1524317: Compiling Python ``--without-threads`` failed.
+ The Python core compiles again then, and, in a build without threads, the
+ new ``sys._current_frames()`` returns a dictionary with one entry,
+ mapping the faux "thread id" 0 to the current frame.
+
Library
-------
@@ -155,9 +160,9 @@ Library
Extension Modules
-----------------
-- #1494314: Fix a regression with high-numbered sockets in 2.4.3. This
- means that select() on sockets > FD_SETSIZE (typically 1024) work again.
- The patch makes sockets use poll() internally where available.
+- #1494314: Fix a regression with high-numbered sockets in 2.4.3. This
+ means that select() on sockets > FD_SETSIZE (typically 1024) work again.
+ The patch makes sockets use poll() internally where available.
- Assigning None to pointer type fields in ctypes structures possible
overwrote the wrong fields, this is fixed now.
@@ -1216,7 +1221,7 @@ Extension Modules
Library
-------
-
+
- Patch #1388073: Numerous __-prefixed attributes of unittest.TestCase have
been renamed to have only a single underscore prefix. This was done to
make subclassing easier.
diff --git a/Python/pystate.c b/Python/pystate.c
index b872dc0..eca26c7 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -387,6 +387,53 @@ PyThreadState_Next(PyThreadState *tstate) {
return tstate->next;
}
+/* The implementation of sys._current_frames(). This is intended to be
+ called with the GIL held, as it will be when called via
+ sys._current_frames(). It's possible it would work fine even without
+ the GIL held, but haven't thought enough about that.
+*/
+PyObject *
+_PyThread_CurrentFrames(void)
+{
+ PyObject *result;
+ PyInterpreterState *i;
+
+ result = PyDict_New();
+ if (result == NULL)
+ return NULL;
+
+ /* for i in all interpreters:
+ * for t in all of i's thread states:
+ * if t's frame isn't NULL, map t's id to its frame
+ * Because these lists can mutute even when the GIL is held, we
+ * need to grab head_mutex for the duration.
+ */
+ HEAD_LOCK();
+ for (i = interp_head; i != NULL; i = i->next) {
+ PyThreadState *t;
+ for (t = i->tstate_head; t != NULL; t = t->next) {
+ PyObject *id;
+ int stat;
+ struct _frame *frame = t->frame;
+ if (frame == NULL)
+ continue;
+ id = PyInt_FromLong(t->thread_id);
+ if (id == NULL)
+ goto Fail;
+ stat = PyDict_SetItem(result, id, (PyObject *)frame);
+ Py_DECREF(id);
+ if (stat < 0)
+ goto Fail;
+ }
+ }
+ HEAD_UNLOCK();
+ return result;
+
+ Fail:
+ HEAD_UNLOCK();
+ Py_DECREF(result);
+ return NULL;
+}
/* Python "auto thread state" API. */
#ifdef WITH_THREAD
@@ -550,54 +597,6 @@ PyGILState_Release(PyGILState_STATE oldstate)
PyEval_SaveThread();
}
-/* The implementation of sys._current_frames(). This is intended to be
- called with the GIL held, as it will be when called via
- sys._current_frames(). It's possible it would work fine even without
- the GIL held, but haven't thought enough about that.
-*/
-PyObject *
-_PyThread_CurrentFrames(void)
-{
- PyObject *result;
- PyInterpreterState *i;
-
- result = PyDict_New();
- if (result == NULL)
- return NULL;
-
- /* for i in all interpreters:
- * for t in all of i's thread states:
- * if t's frame isn't NULL, map t's id to its frame
- * Because these lists can mutute even when the GIL is held, we
- * need to grab head_mutex for the duration.
- */
- HEAD_LOCK();
- for (i = interp_head; i != NULL; i = i->next) {
- PyThreadState *t;
- for (t = i->tstate_head; t != NULL; t = t->next) {
- PyObject *id;
- int stat;
- struct _frame *frame = t->frame;
- if (frame == NULL)
- continue;
- id = PyInt_FromLong(t->thread_id);
- if (id == NULL)
- goto Fail;
- stat = PyDict_SetItem(result, id, (PyObject *)frame);
- Py_DECREF(id);
- if (stat < 0)
- goto Fail;
- }
- }
- HEAD_UNLOCK();
- return result;
-
- Fail:
- HEAD_UNLOCK();
- Py_DECREF(result);
- return NULL;
-}
-
#ifdef __cplusplus
}
#endif