- pythunrun.c, Py_Finalize(): move the call to _Py_PrintReferences()

even farther down, to just before the call to
  _PyObject_DebugMallocStats().  This required the following changes:

- pystate.c, PyThreadState_GetDict(): changed not to raise an
  exception or issue a fatal error when no current thread state is
  available, but simply return NULL without raising an exception
  (ever).

- object.c, Py_ReprEnter(): when PyThreadState_GetDict() returns NULL,
  don't raise an exception but return 0.  This means that when
  printing a container that's recursive, printing will go on and on
  and on.  But that shouldn't happen in the case we care about (see
  first bullet).

- Updated Misc/NEWS and Doc/api/init.tex to reflect changes to
  PyThreadState_GetDict() definition.
This commit is contained in:
Guido van Rossum 2003-04-15 15:12:39 +00:00
parent 6fde1cef4a
commit 0fc8f00252
5 changed files with 28 additions and 17 deletions

View File

@ -677,9 +677,12 @@ interpreter lock has been created.
\begin{cfuncdesc}{PyObject*}{PyThreadState_GetDict}{}
Return a dictionary in which extensions can store thread-specific
state information. Each extension should use a unique key to use to
store state in the dictionary. If this function returns \NULL, an
exception has been raised and the caller should allow it to
propagate.
store state in the dictionary. It is okay to call this function
when no current thread state is available.
If this function returns \NULL, no exception has been raised and the
caller should assume no current thread state is available.
\versionchanged[Previously this could only be called when a current
thread is active, and \NULL meant that an exception was raised]{2.3}
\end{cfuncdesc}

View File

@ -150,6 +150,10 @@ Build
C API
-----
- PyThreadState_GetDict() was changed not to raise an exception or
issue a fatal error when no current thread state is available. This
makes it possible to print dictionaries when no thread is active.
- LONG_LONG was renamed to PY_LONG_LONG.
- Added PyObject_SelfIter() to fill the tp_iter slot for the

View File

@ -2119,7 +2119,7 @@ Py_ReprEnter(PyObject *obj)
dict = PyThreadState_GetDict();
if (dict == NULL)
return -1;
return 0;
list = PyDict_GetItemString(dict, KEY);
if (list == NULL) {
list = PyList_New(0);

View File

@ -266,17 +266,21 @@ PyThreadState_Swap(PyThreadState *new)
/* An extension mechanism to store arbitrary additional per-thread state.
PyThreadState_GetDict() returns a dictionary that can be used to hold such
state; the caller should pick a unique key and store its state there. If
PyThreadState_GetDict() returns NULL, an exception has been raised (most
likely MemoryError) and the caller should pass on the exception. */
PyThreadState_GetDict() returns NULL, an exception has *not* been raised
and the caller should assume no per-thread state is available. */
PyObject *
PyThreadState_GetDict(void)
{
if (_PyThreadState_Current == NULL)
Py_FatalError("PyThreadState_GetDict: no current thread");
return NULL;
if (_PyThreadState_Current->dict == NULL)
_PyThreadState_Current->dict = PyDict_New();
if (_PyThreadState_Current->dict == NULL) {
PyObject *d;
_PyThreadState_Current->dict = d = PyDict_New();
if (d == NULL)
PyErr_Clear();
}
return _PyThreadState_Current->dict;
}

View File

@ -280,14 +280,6 @@ Py_Finalize(void)
/* Clear interpreter state */
PyInterpreterState_Clear(interp);
#ifdef Py_TRACE_REFS
/* Dump references -- this may implicitly need the thread state,
so this is the last possible place where we can do this. */
if (Py_GETENV("PYTHONDUMPREFS")) {
_Py_PrintReferences(stderr);
}
#endif /* Py_TRACE_REFS */
/* Delete current thread */
PyThreadState_Swap(NULL);
PyInterpreterState_Delete(interp);
@ -314,6 +306,14 @@ Py_Finalize(void)
PyGrammar_RemoveAccelerators(&_PyParser_Grammar);
#ifdef Py_TRACE_REFS
/* Dump references -- this may implicitly need the thread state,
so this is the last possible place where we can do this. */
if (Py_GETENV("PYTHONDUMPREFS")) {
_Py_PrintReferences(stderr);
}
#endif /* Py_TRACE_REFS */
#ifdef PYMALLOC_DEBUG
if (Py_GETENV("PYTHONMALLOCSTATS"))
_PyObject_DebugMallocStats();