diff options
-rw-r--r-- | Lib/test/test_sys.py | 22 | ||||
-rw-r--r-- | Misc/NEWS | 13 | ||||
-rw-r--r-- | Python/pystate.c | 95 |
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)) @@ -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 |