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.
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))

View File

@ -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.

View File

@ -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