New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug in _PyDict_Pop() on a splitted table #72307
Comments
In the issue #4a5b61b0d090, Stefan Krah wrote: "The Blaze test suite segfaults with 4a5b61b0d090". I may be related to compact dict and the issue bpo-28040. Stefan: Can you please explain what is Blaze? Explain how to reproduce the issue? Try to get the Python traceback? Did you try a debug build? If you use a release build, please set the env var PYTHONMALLOC=debug. """ For Blaze *itself* there is no difference whether this is fixed now and """ ==3442== Invalid read of size 8 |
Sorry Victor, I have been reporting memory related issues for a long I'm already using Valgrind, why would I set PYTHONMALLOC=debug? |
Valgrind doesn't understand Python frames. PYTHONMALLOC=debug can show you more information from Python internals, especially when using the tracemalloc module: At this point, I'm not convinced that the issue comes from Python itself. It would help if at least you can explain how to reproduce the issue. What is Blaze? Where can I find it? |
Victor, I'm beginning to resent your tone. |
See also the issue bpo-28123: "_PyDict_GetItem_KnownHash ignores DKIX_ERROR return". |
The blaze test suite fails in pytest. $ sudo dnf builddep python-numpy python-h5py
$ virtualenv -p ../bin/python3.6 venvblaze
$ cd venvblaze
$ bin/pip install install blaze pyyaml requests dask pytest h5py
bin/pytest -v lib/python3.6/site-packages/blaze/tests/test_sql.py
=================================================================== test session starts ==================================================================== lib/python3.6/site-packages/blaze/tests/test_sql.py::test_column Aborted (core dumped) #0 0x00007ffff711f6f5 in raise () from /lib64/libc.so.6
#1 0x00007ffff71212fa in abort () from /lib64/libc.so.6
#2 0x00007ffff7117f97 in __assert_fail_base () from /lib64/libc.so.6
#3 0x00007ffff7118042 in __assert_fail () from /lib64/libc.so.6
#4 0x000000000048f12c in _PyDict_Pop (mp=mp@entry=0x7fffbc6bba30, key=0x7fffe07ab270, deflt=0x885ec0 <_Py_NoneStruct>) at Objects/dictobject.c:1743
#5 0x000000000048f274 in dict_pop (mp=0x7fffbc6bba30, args=<optimized out>) at Objects/dictobject.c:2736
#6 0x000000000049767d in _PyCFunction_FastCallDict (func_obj=func_obj@entry=0x7fffbc616850, args=args@entry=0x1c73600, nargs=nargs@entry=2,
kwargs=kwargs@entry=0x0) at Objects/methodobject.c:234
#7 0x00000000004978d4 in _PyCFunction_FastCallKeywords (func=func@entry=0x7fffbc616850, stack=stack@entry=0x1c73600, nargs=nargs@entry=2,
kwnames=kwnames@entry=0x0) at Objects/methodobject.c:295
#8 0x0000000000528c5e in call_function (pp_stack=pp_stack@entry=0x7fffffff1678, oparg=oparg@entry=2, kwnames=kwnames@entry=0x0) at Python/ceval.c:4763
#9 0x00000000005321d4 in _PyEval_EvalFrameDefault (f=0x1c73448, throwflag=<optimized out>) at Python/ceval.c:3250
#10 0x0000000000527d6b in PyEval_EvalFrameEx (f=f@entry=0x1c73448, throwflag=throwflag@entry=0) at Python/ceval.c:718
#11 0x0000000000527e3b in _PyFunction_FastCall (co=<optimized out>, args=0x7fffbc6245e0, nargs=nargs@entry=2, globals=<optimized out>)
at Python/ceval.c:4845
#12 0x0000000000528a8b in fast_function (func=func@entry=0x7fffe06e69b0, stack=<optimized out>, nargs=nargs@entry=2, kwnames=kwnames@entry=0x0)
at Python/ceval.c:4880
#13 0x0000000000528d19 in call_function (pp_stack=pp_stack@entry=0x7fffffff1828, oparg=oparg@entry=1, kwnames=kwnames@entry=0x0) at Python/ceval.c:4784
#14 0x00000000005321d4 in _PyEval_EvalFrameDefault (f=0x7fffbc624438, throwflag=<optimized out>) at Python/ceval.c:3250
#15 0x0000000000527d6b in PyEval_EvalFrameEx (f=f@entry=0x7fffbc624438, throwflag=throwflag@entry=0) at Python/ceval.c:718
#16 0x0000000000527e3b in _PyFunction_FastCall (co=co@entry=0x7fffe061df40, args=0x7fffffff19d0, args@entry=0x7fffffff19c0, nargs=nargs@entry=2,
globals=globals@entry=0x7fffe06a4f58) at Python/ceval.c:4845
#17 0x0000000000533f46 in _PyFunction_FastCallDict (func=func@entry=0x7fffe05f7f70, args=args@entry=0x7fffffff19c0, nargs=nargs@entry=2,
kwargs=kwargs@entry=0x0) at Python/ceval.c:4947
#18 0x0000000000446837 in _PyObject_FastCallDict (func=func@entry=0x7fffe05f7f70, args=args@entry=0x7fffffff19c0, nargs=2, kwargs=kwargs@entry=0x0)
at Objects/abstract.c:2297
#19 0x00000000004479da in PyObject_CallFunctionObjArgs (callable=0x7fffe05f7f70) at Objects/abstract.c:2811
#20 0x00000000005b2888 in property_descr_set (self=<optimized out>, obj=<optimized out>, value=<optimized out>) at Objects/descrobject.c:1419
#21 0x000000000049bf42 in _PyObject_GenericSetAttrWithDict (obj=0x7fffbc695058, name=0x7ffff02bcba0, value=0x885ec0 <_Py_NoneStruct>, dict=dict@entry=0x0)
at Objects/object.c:1152
#22 0x000000000049c174 in PyObject_GenericSetAttr (obj=<optimized out>, name=<optimized out>, value=<optimized out>) at Objects/object.c:1194
#23 0x000000000049b823 in PyObject_SetAttr (v=v@entry=0x7fffbc695058, name=<optimized out>, name@entry=0x7ffff02bcba0,
value=value@entry=0x885ec0 <_Py_NoneStruct>) at Objects/object.c:932
#24 0x000000000052e4eb in _PyEval_EvalFrameDefault (f=0x1c73218, throwflag=<optimized out>) at Python/ceval.c:2248
#25 0x0000000000527d6b in PyEval_EvalFrameEx (f=f@entry=0x1c73218, throwflag=throwflag@entry=0) at Python/ceval.c:718
#26 0x000000000052884a in _PyEval_EvalCodeWithName (_co=0x7fffe061dd00, globals=<optimized out>, locals=locals@entry=0x0, args=<optimized out>,
argcount=3, kwnames=0x0, kwargs=0x1c8a460, kwcount=0, kwstep=1, defs=0x7fffe06213c8, defcount=3, kwdefs=0x0, closure=0x0, name=0x7ffff7f7e430,
qualname=0x7fffe061ab08) at Python/ceval.c:4094
#27 0x00000000005289ba in fast_function (func=func@entry=0x7fffe05f7d48, stack=<optimized out>, nargs=nargs@entry=3, kwnames=kwnames@entry=0x0)
at Python/ceval.c:4904
#28 0x0000000000528d19 in call_function (pp_stack=pp_stack@entry=0x7fffffff1e38, oparg=oparg@entry=2, kwnames=kwnames@entry=0x0) at Python/ceval.c:4784
---Type <return> to continue, or q <return> to quit---
#29 0x00000000005321d4 in _PyEval_EvalFrameDefault (f=0x1c8a288, throwflag=<optimized out>) at Python/ceval.c:3250
#30 0x0000000000527d6b in PyEval_EvalFrameEx (f=f@entry=0x1c8a288, throwflag=throwflag@entry=0) at Python/ceval.c:718
#31 0x000000000052884a in _PyEval_EvalCodeWithName (_co=_co@entry=0x7fffe06a2ac0, globals=globals@entry=0x7fffe07012b0, locals=locals@entry=0x0,
args=args@entry=0x7fffffff2080, argcount=argcount@entry=3, kwnames=kwnames@entry=0x7fffbc670bc0, kwargs=0x7fffbc670bc8, kwcount=8, kwstep=2, defs=0x0,
defcount=0, kwdefs=0x0, closure=0x7fffe037a6d8, name=0x7ffff7f7e430, qualname=0x7fffe0351120) at Python/ceval.c:4094
#32 0x0000000000534020 in _PyFunction_FastCallDict (func=func@entry=0x7fffe02978f8, args=args@entry=0x7fffffff2080, nargs=nargs@entry=3,
kwargs=kwargs@entry=0x7fffbc6bb8c8) at Python/ceval.c:4996
#33 0x0000000000446837 in _PyObject_FastCallDict (func=func@entry=0x7fffe02978f8, args=args@entry=0x7fffffff2080, nargs=nargs@entry=3,
kwargs=kwargs@entry=0x7fffbc6bb8c8) at Objects/abstract.c:2297
#34 0x0000000000446acb in _PyObject_Call_Prepend (func=0x7fffe02978f8, obj=obj@entry=0x7fffbc695058, args=0x7fffbc0f22f8, kwargs=0x7fffbc6bb8c8)
at Objects/abstract.c:2360
#35 0x0000000000460410 in method_call (method=<optimized out>, args=<optimized out>, kwargs=<optimized out>) at Objects/classobject.c:317
#36 0x000000000044652e in PyObject_Call (func=func@entry=0x7fffbdf9ef38, args=args@entry=0x7fffbc0f22f8, kwargs=kwargs@entry=0x7fffbc6bb8c8)
at Objects/abstract.c:2248
#37 0x00000000004b4dcb in slot_tp_init (self=<optimized out>, args=0x7fffbc0f22f8, kwds=0x7fffbc6bb8c8) at Objects/typeobject.c:6359
#38 0x00000000004b128b in type_call (type=0x16f0168, args=0x7fffbc0f22f8, kwds=0x7fffbc6bb8c8) at Objects/typeobject.c:915
#39 0x000000000044652e in PyObject_Call (func=0x16f0168, args=0x7fffbc0f22f8, kwargs=0x7fffbc6bb8c8) at Objects/abstract.c:2248
#40 0x0000000000527237 in do_call_core (func=func@entry=0x16f0168, callargs=callargs@entry=0x7fffbc0f22f8, kwdict=kwdict@entry=0x7fffbc6bb8c8)
at Python/ceval.c:5032
#41 0x0000000000532700 in _PyEval_EvalFrameDefault (f=0x1c2a6c8, throwflag=<optimized out>) at Python/ceval.c:3332
#42 0x0000000000527d6b in PyEval_EvalFrameEx (f=f@entry=0x1c2a6c8, throwflag=throwflag@entry=0) at Python/ceval.c:718
#43 0x000000000052884a in _PyEval_EvalCodeWithName (_co=0x7fffe0391700, globals=<optimized out>, locals=locals@entry=0x0, args=<optimized out>,
argcount=2, kwnames=0x7fffe0336ad0, kwargs=0x1cb3998, kwcount=3, kwstep=1, defs=0x7fffe06a4800, defcount=3, kwdefs=0x0, closure=0x0,
name=0x7fffe06707b0, qualname=0x7fffe03504f0) at Python/ceval.c:4094
#44 0x00000000005289ba in fast_function (func=func@entry=0x7fffe0297f70, stack=<optimized out>, nargs=nargs@entry=2, kwnames=kwnames@entry=0x7fffe0336aa8)
at Python/ceval.c:4904
#45 0x0000000000528d19 in call_function (pp_stack=pp_stack@entry=0x7fffffff24f0, oparg=<optimized out>, kwnames=kwnames@entry=0x7fffe0336aa8)
at Python/ceval.c:4784
#46 0x00000000005322ed in _PyEval_EvalFrameDefault (f=0x1cb37d8, throwflag=<optimized out>) at Python/ceval.c:3266
#47 0x0000000000527d6b in PyEval_EvalFrameEx (f=f@entry=0x1cb37d8, throwflag=throwflag@entry=0) at Python/ceval.c:718
#48 0x0000000000527e3b in _PyFunction_FastCall (co=<optimized out>, args=0x7fffbc644970, nargs=nargs@entry=1, globals=<optimized out>)
at Python/ceval.c:4845
#49 0x0000000000528a8b in fast_function (func=func@entry=0x7fffe02ef3f0, stack=<optimized out>, nargs=nargs@entry=1, kwnames=kwnames@entry=0x0)
at Python/ceval.c:4880
#50 0x0000000000528d19 in call_function (pp_stack=pp_stack@entry=0x7fffffff2698, oparg=oparg@entry=0, kwnames=kwnames@entry=0x0) at Python/ceval.c:4784
#51 0x00000000005321d4 in _PyEval_EvalFrameDefault (f=0x7fffbc6447d8, throwflag=<optimized out>) at Python/ceval.c:3250
#52 0x0000000000527d6b in PyEval_EvalFrameEx (f=f@entry=0x7fffbc6447d8, throwflag=throwflag@entry=0) at Python/ceval.c:718
#53 0x0000000000527e3b in _PyFunction_FastCall (co=<optimized out>, args=0x1cb7eb0, nargs=nargs@entry=1, globals=<optimized out>) at Python/ceval.c:4845
#54 0x0000000000528a8b in fast_function (func=func@entry=0x7fffe02d0788, stack=<optimized out>, nargs=nargs@entry=1, kwnames=kwnames@entry=0x0)
at Python/ceval.c:4880
#55 0x0000000000528d19 in call_function (pp_stack=pp_stack@entry=0x7fffffff2848, oparg=oparg@entry=1, kwnames=kwnames@entry=0x0) at Python/ceval.c:4784
---Type <return> to continue, or q <return> to quit---
#56 0x00000000005321d4 in _PyEval_EvalFrameDefault (f=0x1cb7cf8, throwflag=<optimized out>) at Python/ceval.c:3250
#57 0x0000000000527d6b in PyEval_EvalFrameEx (f=f@entry=0x1cb7cf8, throwflag=throwflag@entry=0) at Python/ceval.c:718
#58 0x0000000000527e3b in _PyFunction_FastCall (co=co@entry=0x7fffe0738d00, args=0x7fffffff29f8, args@entry=0x7fffffff29e0, nargs=nargs@entry=3,
globals=globals@entry=0x7fffe0a7fc88) at Python/ceval.c:4845
#59 0x0000000000533f46 in _PyFunction_FastCallDict (func=func@entry=0x7fffe06e6618, args=args@entry=0x7fffffff29e0, nargs=nargs@entry=3,
kwargs=kwargs@entry=0x0) at Python/ceval.c:4947
#60 0x0000000000446837 in _PyObject_FastCallDict (func=func@entry=0x7fffe06e6618, args=args@entry=0x7fffffff29e0, nargs=3, kwargs=kwargs@entry=0x0)
at Objects/abstract.c:2297
#61 0x00000000004479da in PyObject_CallFunctionObjArgs (callable=0x7fffe06e6618) at Objects/abstract.c:2811
#62 0x00000000004b6930 in slot_tp_descr_get (self=self@entry=0x7fffe0340810, obj=obj@entry=0x7fffbc692f60, type=0x16e2238) at Objects/typeobject.c:6330
#63 0x000000000049bde4 in _PyObject_GenericGetAttrWithDict (obj=0x7fffbc692f60, name=0x7ffff7e82450, dict=<optimized out>, dict@entry=0x0)
at Objects/object.c:1099
... |
$ PYTHONFAULTHANDLER=1 bin/pytest -v lib/python3.6/site-packages/blaze/tests/test_sql.py
=================================================================== test session starts ==================================================================== lib/python3.6/site-packages/blaze/tests/test_sql.py::test_column Aborted (core dumped) lib/python3.6/site-packages/blaze/tests/test_sql.py::test_column python3.6: Objects/dictobject.c:1743: _PyDict_Pop: Assertion `ix >= 0' failed. Thread 0x00007f9671ffb700 (most recent call first): Thread 0x00007f96727fc700 (most recent call first): Thread 0x00007f9672ffd700 (most recent call first): Thread 0x00007f96737fe700 (most recent call first): Thread 0x00007f9673fff700 (most recent call first): Thread 0x00007f9688fb9700 (most recent call first): Thread 0x00007f96897ba700 (most recent call first): Thread 0x00007f9689fbb700 (most recent call first): Thread 0x00007f968a7bc700 (most recent call first): Thread 0x00007f968afbd700 (most recent call first): Thread 0x00007f968b7be700 (most recent call first): Current thread 0x00007f96a3ebc700 (most recent call first): |
It's a bug in sqlalchemy. The test suite of sqlalchemy is crashing, too. $ PYTHONFAULTHANDLER=1 ../bin/pytest -v -s
=================================================================== test session starts ==================================================================== test/aaa_profiling/test_compiler.py::CompileTest_sqlite_pysqlite::test_insert SKIPPED Current thread 0x00007f5606ac8700 (most recent call first): |
It fails in pytest and has a segfault. The pytest issue should probably This is a minimal reproducer for the segfault: ========================================================= from blaze.expr import symbol
from blaze.interactive import data
from blaze.compute import compute
t = symbol('t', 'var * {amount: int64, id: int64, name: string}')
sql = data('sqlite:///:memory:::accounts', dshape=t.dshape)
expr = t.distinct().nrows
x = expr._subs({t: sql})
result = compute(x) ========================================================= Blaze itself is pure Python, a third part issue could be in sqlite |
The issue is not related to Blaze. It is caused by a SQLAlchemy method. expire_instance() calls pop(name, None) on instance __dict__. |
Thanks, Christian! |
I added debug traces to _PyDict_Pop(). It looks like the assertion failed after dictresize() converts a splitted table into a combined table. After the resize, the key '_columns_plus_names' cannot be found anymore, whereas it was found before. The string thing about the key '_columns_plus_names' is that I cannot see it in the output of repr(dict). The length of the dictionary is 7, but it looks like it contains 8 items... Something is wrong, no? Note: I'm not sure that my debug traces are correct, especially the number of entries may be larger. I don't understand yet exactly the internal structure of dictionaries. @@ delete memoized before resize: index[0]=-1 entry[0]: key='_auto_correlate', hash=-4930419206435490684 object : {'_auto_correlate': True, '_from_obj': OrderedSet([]), '_raw_columns': [Table('t1', MetaData(bind=None), Column('c1', Integer(), table=<t1>, primary_key=True, nullable=False), Column('c2', String(length=30), table=<t1>), schema=None)], '_whereclause': <sqlalchemy.sql.elements.BinaryExpression object at 0x7fffe93d1190>, '_having': None, 'use_labels': False, '_bind': None} after resize: <combined dict 0x7fffe93cda30 used=7 keys->dk_size=32 keys->dk_nentries=7 keys->dk_usable=14 || usable=21> index[0]=-1 entry[0]: key='_auto_correlate', value=True, hash=-4930419206435490684 object : {'_auto_correlate': True, '_from_obj': OrderedSet([]), '_raw_columns': [Table('t1', MetaData(bind=None), Column('c1', Integer(), table=<t1>, primary_key=True, nullable=False), Column('c2', String(length=30), table=<t1>), schema=None)], '_whereclause': <sqlalchemy.sql.elements.BinaryExpression object at 0x7fffe93d1190>, '_having': None, 'use_labels': False, '_bind': None} python: Objects/dictobject.c:1810: _PyDict_Pop: Assertion `ix >= 0' failed. Program received signal SIGABRT, Aborted. |
To reproduce the issue:
tar -xf ../SQLAlchemy-1.1.0b3.tar.gz I get: Current thread 0x00007f6d909da700 (most recent call first): |
No need, you can reproduce it by this: >>> class C:
... pass
...
>>> a, b = C(), C()
>>> a.a, a.b = 1, 2
>>> b.a = 1
>>> b.__dict__.pop('b')
python: Objects/dictobject.c:1739: _PyDict_Pop: Assertion `ix >= 0' failed.
Aborted (core dumped) |
I submit a patch that can solve this. Actually I find it before but forget about it.... |
Good work! This example is a bit easier to understand: class Cls:
pass
a = Cls()
a.x = 1
a.y = 2
b = Cls()
b.x = 1
print(hasattr(b, 'y'))
print(b.__dict__.pop('y', None)) $ ./python d.py
False
python: Objects/dictobject.c:1743: _PyDict_Pop: Assertion `ix >= 0' failed.
Aborted (core dumped) |
v2 now enhances existing dict.pop() unittest to cover this case. |
New changeset dc627ef9020f by Victor Stinner in branch '3.6': |
Thanks Stefan Krah for the bug report, thanks Christian Heimes for helping to identify the bug, and obvious thanks to Xiang Zhang to write a fix with an unit test ;-) |
Oh, very thank you, Xiang. |
Misc/NEWS
so that it is managed by towncrier #552Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: