[Python-Dev] Why is nb_inplace_add copied to sq_inplace_concat?
Matt Newell
newellm at blur.com
Fri May 17 01:17:20 CEST 2013
I have encountered what I believe to be a bug but I'm sure there is some
reason things are done as they are and I am hoping someone can shed some light
or confirm it is indeed a bug.
As a bit of background I have a c++ class that I use sip to generate python
bindings. The potential python bug manifests itself as:
>>> rl = RecordList()
>>> rl += []
>>> rl
NotImplemented
The bindings fill in nb_inplace_add which appears to be implemented properly,
returning a new reference to Py_NotImplemented if the right hand argument is
not as expected.
Where things appear to go wrong is that PyNumber_InPlaceAdd, after getting a
NotImplemented return value from nb_inplace_add, then attempts to call
sq_inplace_concat. From reading the code it appears that sq_inplace_concat is
not supposed to return NotImplemented, instead it should set an exception and
return null if the right hand arg is not supported. In my case
sq_inplace_concat ends up being the same function as nb_inplace_add, which
results in the buggy behavior.
When I figured this out I tried to find out why sq_inplace_concat was set to the
same function as nb_inplace_add, and ended up having to set a watchpoint in
gdb which finally gave me the answer that python itself is setting
sq_inplace_concat during type creation in the various functions in
typeobject.c. Stack trace is below.
I don't really understand what the fixup_slot_dispatchers function is doing,
but it does seem like there must be a bug either in what it's doing, or in
PyNumber_InPlaceAdd's handling of a NotImplemented return value from
sq_inplace_concat.
Thanks,
Matt
Python 2.7.3 (default, Jan 2 2013, 13:56:14)
[GCC 4.7.2] on linux2
Stack trace where a watch on sq->sq_inplace_concat reveals the change:
Hardware watchpoint 5: *(binaryfunc *) 0xcf6f88
Old value = (binaryfunc) 0
New value = (binaryfunc) 0x7ffff4d41c78 <slot_RecordList___iadd__(PyObject*,
PyObject*)>
#0 update_one_slot.25588 (type=type at entry=0xcf6c70, p=0x86ba90) at
../Objects/typeobject.c:6203
#1 0x00000000004b96d0 in fixup_slot_dispatchers (type=0xcf6c70) at
../Objects/typeobject.c:6299
#2 type_new.part.40 (kwds=<optimized out>, args=0x0, metatype=<optimized
out>) at ../Objects/typeobject.c:2464
#3 type_new.25999 (metatype=<optimized out>, args=0x0, kwds=<optimized out>)
at ../Objects/typeobject.c:2048
#4 0x0000000000463c08 in type_call.25547 (type=0x7ffff65953a0,
args=('RecordList', (<sip.wrappertype at remote 0x7ffff5201080>,),
{'__module__': 'blur.Stone'}), kwds=0x0) at ../Objects/typeobject.c:721
#5 0x00000000004644eb in PyObject_Call (func=<type at remote 0x7ffff65953a0>,
arg=<optimized out>, kw=<optimized out>) at ../Objects/abstract.c:2529
More information about the Python-Dev
mailing list