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:
Tim Peters 2006-07-19 00:03:19 +00:00
parent 73a9eade1c
commit 112aad3630
3 changed files with 78 additions and 52 deletions

View File

@ -239,6 +239,19 @@ class SysModuleTest(unittest.TestCase):
# sys._current_frames() is a CPython-only gimmick. # sys._current_frames() is a CPython-only gimmick.
def test_current_frames(self): 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 threading, thread
import traceback import traceback
@ -298,6 +311,15 @@ class SysModuleTest(unittest.TestCase):
leave_g.set() leave_g.set()
t.join() 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): def test_attributes(self):
self.assert_(isinstance(sys.api_version, int)) self.assert_(isinstance(sys.api_version, int))
self.assert_(isinstance(sys.argv, list)) self.assert_(isinstance(sys.argv, list))

View File

@ -24,6 +24,11 @@ Core and builtins
again. Fixing this problem required changing the .pyc magic number. again. Fixing this problem required changing the .pyc magic number.
This means that .pyc files generated before 2.5c1 will be regenerated. 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 Library
------- -------

View File

@ -387,6 +387,53 @@ PyThreadState_Next(PyThreadState *tstate) {
return tstate->next; 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. */ /* Python "auto thread state" API. */
#ifdef WITH_THREAD #ifdef WITH_THREAD
@ -550,54 +597,6 @@ PyGILState_Release(PyGILState_STATE oldstate)
PyEval_SaveThread(); 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 #ifdef __cplusplus
} }
#endif #endif