无论我尝试使用什么版本的Python(2.7,3.2,3.4),我都会在这行代码中得到一个段错误:
Program received signal SIGSEGV, Segmentation fault.
_PyObject_Malloc (ctx=0x0, nbytes=50) at Objects/obmalloc.c:1159
1159 if ((pool->freeblock = *(block **)bp) != NULL) {
我的应用程序是一个mod_wsgi应用程序,我正在使用OpenSSL的C扩展(但我看到C扩展中没有错误,即使使用vagrind)。我无法使用valgrind重现错误,但valgrind会提供大量错误,这些错误不会被提供的python抑制文件抑制。例如:
==4800== Use of uninitialised value of size 8
==4800== at 0xD95E42A: PyEval_EvalFrameEx (ceval.c:2430)
==4800== by 0xD964614: PyEval_EvalCodeEx (ceval.c:3585)
==4800== by 0xD8C092F: function_call (funcobject.c:632)
==4800== by 0xD89411E: PyObject_Call (abstract.c:2067)
==4800== by 0xD95FC23: PyEval_EvalFrameEx (ceval.c:4558)
==4800== by 0xD964614: PyEval_EvalCodeEx (ceval.c:3585)
==4800== by 0xD8C080E: function_call (funcobject.c:632)
==4800== by 0xD89411E: PyObject_Call (abstract.c:2067)
==4800== by 0xD95FC23: PyEval_EvalFrameEx (ceval.c:4558)
==4800== by 0xD963BE0: PyEval_EvalFrameEx (ceval.c:4331)
==4800== by 0xD963BE0: PyEval_EvalFrameEx (ceval.c:4331)
==4800== by 0xD964614: PyEval_EvalCodeEx (ceval.c:3585)
我在这个特定的实例中使用mod_wsgi版本4.3.0和Python 3.4.2,但其他版本也失败了。它总是在if ((pool->freeblock = *(block **)bp) != NULL) {
线上。
使用错误的C扩展来崩溃Python运行时非常非常容易。
引用计数中的一个非常小的错误或内存处理中的小损坏会使系统不稳定。实际的碰撞位置通常不会给故障的真正原因提供任何可行的暗示,因为很多时候真正的碰撞发生在原因之后很久。
我不能多说valgrind错误,但我也会说扩展中没有valgrind错误并不意味着没有错误。例如,Valgrind不知道Python运行时的引用计数系统 - 引用计数中的小错误通常是崩溃的原因。此外,您在Python运行时中获得“未初始化的值”错误可能是因为存在引用计数错误。当C扩展创建这样的情况时,运行时代码会导致麻烦 - 原因不是在运行时,而是在扩展中,而不是。
在没有看到C扩展的情况下,我想不可能进行进一步的诊断。您是自己实现扩展还是一些开源软件?广泛传播吗?
我会尝试缩小扩展的功能,当使用时,创建麻烦。如果幸运的话,可以使用一组特殊参数将其缩小为一个函数调用。也许作者可以帮助找到错误?
我们的应用程序以相同的方式在3.5.2(Ubuntu 16)上运行崩溃,但在我们的例子中,我们的C代码仅通过PyGObject API与Python交互,我们从不直接操作PyObject引用计数。
经过一些调试,发现问题是issue 26617,它在3.5.3(以及3.6.0及更高版本)中得到修复。这个问题导致PyObject的双重自由,它会破坏可用的内存链并最终导致这种特定的损坏。