[Python-Dev] Crash in new "trashcan" mechanism.

Christian Tismer tismer@tismer.com
Mon, 10 Apr 2000 16:24:24 +0200


About extensions and Trashcan.

Mark Hammond wrote:
...
> Ive struck a crash in the new trashcan mechanism (so I guess Chris
> is gunna pay the most attention here).  Although I can only provoke
> this reliably in debug builds, I believe it also exists in release
> builds, but is just far more insidious.
> 
> Unfortunately, I also can not create a simple crash case.  But I
> _can_ provide info on how you can reliably cause the crash.
> Obviously only tested on Windows...
...
> You will get a crash, and the debugger will show you are destructing
> a list, with an invalid object.  The crash occurs about 1000 times
> after this code is first hit, and I can't narrow the crash condition
> down :-(

The trashcan is built in a quite simple manner. It uses a List
to delay deletions if the nesting level is deep.
The list operations are not thread safe.

A special case is handled: It *could* happen on destruction
of the session, that trashcan cannot handle errors, since
the thread state is already undefined.

But the general case of no interpreter lock is undefined and
forbidden.

In a discussion with Guido, we first thought that we would
need some thread safe object for the delay. Later on it
turned out that it must be generally *forbidden* to destroy
an object when the interpreter lock is not held.

Reason: An instance destruction might call __del__, and that
would run an interpreter without lock. Forbidden.
For that reason, I kept the list in place.

I think it is fine that it crashed.
There are obviously extension modules left
where the interpreter lock rule is violated.
The builtin Python code has been checked, there
are most probably no holes, including tkinter.
Or, I made a mistake in this little code:

void
_PyTrash_deposit_object(op)
	PyObject *op;
{
	PyObject *error_type, *error_value, *error_traceback;

	if (PyThreadState_GET() != NULL)
	    PyErr_Fetch(&error_type, &error_value, &error_traceback);

	if (!_PyTrash_delete_later)
		_PyTrash_delete_later = PyList_New(0);
	if (_PyTrash_delete_later)
		PyList_Append(_PyTrash_delete_later, (PyObject *)op);

	if (PyThreadState_GET() != NULL)
	    PyErr_Restore(error_type, error_value, error_traceback);
}

void
_PyTrash_destroy_list()
{
	while (_PyTrash_delete_later) {
		PyObject *shredder = _PyTrash_delete_later;
		_PyTrash_delete_later = NULL;
		++_PyTrash_delete_nesting;
		Py_DECREF(shredder);
		--_PyTrash_delete_nesting;
	}
}

ciao - chris

-- 
Christian Tismer             :^)   <mailto:tismer@appliedbiometrics.com>
Applied Biometrics GmbH      :     Have a break! Take a ride on Python's
Kaunstr. 26                  :    *Starship* http://starship.python.net
14163 Berlin                 :     PGP key -> http://wwwkeys.pgp.net
PGP Fingerprint       E182 71C7 1A9D 66E9 9D15  D3CC D4D7 93E2 1FAE F6DF
     where do you want to jump today?   http://www.stackless.com