[Python-Dev] PEP 231, __findattr__()

Christian Tismer tismer@tismer.com
Sat, 02 Dec 2000 18:55:21 +0200


Moshe Zadka wrote:
> 
> On Fri, 1 Dec 2000, Barry A. Warsaw wrote:
> 
> > I've just uploaded PEP 231, which describes a new hook in the instance
> > access mechanism, called __findattr__() after a similar mechanism that
> > exists in Jython (but is not exposed at the Python layer).
> 
> There's one thing that bothers me about this: what exactly is "the
> call stack"? Let me clarify: what happens when you have threads.
> Either machine-level threads and stackless threads confuse the issues
> here, not to talk about stackless continuations. Can you add a few
> words to the PEP about dealing with those?

As far as I understood the patch (just skimmed), thee is no
stack involved directly, but the instance increments and decrments
a variable infindattr.

+       if (v != NULL && !inst->infindaddr &&
+           (func = inst->in_class->cl_findattr))
+       {
+               PyObject *args, *res;
+               args = Py_BuildValue("(OOO)", inst, name, v);
+               if (args == NULL)
+                       return -1;
+               ++inst->infindaddr;
+               res = PyEval_CallObject(func, args);
+               --inst->infindaddr;

This is: The call modifies the instance's state, while calling
the findattr method.
You are right: I see a serious problem with this. It doesn't
even need continuations to get things messed up. Guido's
proposed coroutines, together with uThread-Switching, might
be able to enter the same instance twice with ease.

Barry, after second thought, I feel this can become
a problem in the future. This infindattr attribute
only works correctly if we are guaranteed to use
strict stack order of execution.
What you're *intending* to to is to tell the PyEval_CallObject
that it should not find the __findattr__ attribute. But
this should be done only for this call and all of its descendants,
but no *fresh* access from elsewhere.

The hard way to get out of this would be to stop scheduling
in that case. Maybe this is very cheap, but quite unelegant.

We have a quite peculiar system state here: A function call
acts like an escape, to make all subsequent calls behave
differently, until this call is finished.

Without blocking microthreads, a clean way to do this would be
a search up in the frame chain, if there is a running __findattr__
method of this object. Fairly expensive. Well, the problem
also exists with real threads, if they are allowed to switch
in such a context.

I fear it is necessary to either block this stuff until it is
ready, or to maintain some thread-wise structure for the
state of this object.

Ok, after thinking some more, I'll start an extra message
to Barry on this topic.

cheers - chris

-- 
Christian Tismer             :^)   <mailto:tismer@tismer.com>
Mission Impossible 5oftware  :     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