SF bug 1524317: configure --without-threads fails to build
Moved the code for _PyThread_CurrentFrames() up, so it's no longer in a huge "#ifdef WITH_THREAD" block (I didn't realize it /was/ in one). Changed test_sys's test_current_frames() so it passes with or without thread supported compiled in. Note that test_sys fails when Python is compiled without threads, but for an unrelated reason (the old test_exit() fails with an indirect ImportError on the `thread` module). There are also other unrelated compilation failures without threads, in extension modules (like ctypes); at least the core compiles again. Do we really support --without-threads? If so, there are several problems remaining.
This commit is contained in:
parent
73a9eade1c
commit
112aad3630
|
@ -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
|
||||
-------
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue