【问题标题】:Segfault in Cython callbackCython 回调中的段错误
【发布时间】:2015-09-03 23:26:08
【问题描述】:

我目前有点卡住,希望得到一些指导。我有一个包装 sqlite 的小模块,我想允许使用 sqlite 提供的钩子执行用户定义的 Python 函数。

这是来自 SQLite 头文件的定义:

cdef extern from "sqlite3.h":
    cdef void *sqlite3_commit_hook(sqlite3*, int(*xFunc)(void*), void*)

这是对应的 Cython:

# Reference to user-provided function.
cdef object py_commit_hook = None

# Typedef for callback
ctypedef int(*commit_callback)(void *data)

# Wrapper function that will in turn call the user-provided python callback.
cdef int commit_hook_wrapper(void *data):
    print 'hello'  # Just for debugging.
    py_commit_hook()

# API used to set callback and make sqlite3 library call.
def set_commit_hook(DatabaseHelper db, callback):
    cdef commit_callback f
    global py_commit_hook

    py_commit_hook = callback
    f = commit_hook_wrapper

    sqlite3_commit_hook(db.db, f, <void *>0)

使用 gdb,这里是回溯:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b16e2d in PySys_GetObject () from /usr/lib/libpython2.7.so.1.0
(gdb) bt
#0  0x00007ffff7b16e2d in PySys_GetObject () from /usr/lib/libpython2.7.so.1.0
#1  0x00007ffff567d291 in __Pyx_GetStdout () at pysqlite_ext.c:6121
#2  __Pyx_PrintOne (f=0x0, o=0x7ffff7e39270) at pysqlite_ext.c:6227
#3  __pyx_f_12pysqlite_ext_commit_hook_wrapper (__pyx_v_data=<optimized out>)
    at pysqlite_ext.c:2526
#4  0x00007ffff58ffb36 in ?? () from /usr/lib/libsqlite3.so.0
#5  0x00007ffff590ac5e in ?? () from /usr/lib/libsqlite3.so.0
#6  0x00007ffff590bd4f in sqlite3_step () from /usr/lib/libsqlite3.so.0
#7  0x00007ffff5b6ffb0 in pysqlite_step ()
   from /usr/lib/python2.7/lib-dynload/_sqlite3.so

commit_hook_wrapper 函数中的print 调用似乎失败了:

(gdb) f 1
#1  0x00007ffff567d291 in __Pyx_GetStdout () at pysqlite_ext.c:6121
6121        PyObject *f = PySys_GetObject((char *)"stdout");
(gdb) l
6116        }
6117    }
6118    
6119    #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION < 3
6120    static PyObject *__Pyx_GetStdout(void) {
6121        PyObject *f = PySys_GetObject((char *)"stdout");
6122        if (!f) {
6123            PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
6124        }
6125        return f;

我完全被难住了!有什么想法可能出了什么问题?

我正在动态链接到 libsqlite3,我想知道这是否是问题所在。我之前已经按照这些思路实现了回调并且从未遇到过问题,但是这次无论我尝试什么似乎都失败了。

【问题讨论】:

    标签: python c sqlite cython


    【解决方案1】:

    从 cython-users 列表中,有人建议我将回调声明为“with gil”。解决了它:

    cdef int commit_hook_wrapper(void *data) with gil:
        print 'hello'
        py_commit_hook()
    

    【讨论】:

      【解决方案2】:

      可以在此处找到有关您的问题的一些信息: (对不起,我还不能发表评论) http://docs.cython.org/en/latest/src/userguide/external_C_code.html#acquiring-and-releasing-the-gil

      在没有 GIL 的情况下执行的 C 代码中用作回调的 C 函数需要先获取 GIL,然后才能操作 Python 对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多