【问题标题】:Cython GIL SIGSEGVCython GIL SIGSEGV
【发布时间】:2014-04-20 01:02:15
【问题描述】:

我在尝试通过来自 Cython 的 LD_PRELOAD 拦截调用时遇到分段违规。我不明白为什么?

"""An experiment in shimming from Cython / Python."""

cdef extern from "dlfcn.h":
    void* dlsym(void*, char*)
    void* RTLD_NEXT

cdef extern int execvp(const char *file, char *const argv[]) with gil:
    print "Intercepted lookup of %r" % file
    libc_execvp = dlsym(RTLD_NEXT, "execvp")
    if libc_execvp:
        with nogil:
            return (<int(*)(const char*, char * const *) nogil>libc_execvp)(file, argv)
    return -1

带有示例测试用例的项目可在https://github.com/CraigJPerry/pyshim/blob/master/pyshim/pyshim.pyx获得

我相信 python 运行时可能没有正确初始化,这是我问题的根源吗?

[craig@d1 pyshim](master)$ gdb env
..
Reading symbols from /usr/bin/env...Reading symbols from /usr/bin/env...(no debugging symbols found)...done.
(gdb) set environment LD_PRELOAD=pyshim/pyshim.so
(gdb) set args echo
(gdb) run
Starting program: /usr/bin/env echo
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x000000396ee0ddb0 in sem_wait () from /lib64/libpthread.so.0
(gdb) bt
#0  0x000000396ee0ddb0 in sem_wait () from /lib64/libpthread.so.0
#1  0x0000003bbcf0c7b5 in PyThread_acquire_lock ()
   from /lib64/libpython2.7.so.1.0
#2  0x0000003bbcefad80 in ?? () from /lib64/libpython2.7.so.1.0
#3  0x0000003bbcefb62c in PyGILState_Ensure () from /lib64/libpython2.7.so.1.0
#4  0x00007ffff7df9519 in execvp (__pyx_v_file=0x7fffffffe85b "echo", 
    __pyx_v_argv=0x7fffffffe4d0) at pyshim/pyshim.c:681
#5  0x0000000000401a82 in main ()

【问题讨论】:

    标签: cython ld-preload


    【解决方案1】:

    Cython 假设您正在运行一个功能性 Python 解释器(即您正在编写一个扩展模块)。在这种情况下,您是嵌入 Python,而不是扩展它。所以你需要做一些额外的工作来初始化一切。

    幸运的是,这并不是一个真正具有挑战性的问题:

    """An experiment in shimming from Cython / Python."""
    
    cdef extern from "dlfcn.h":
        void* dlsym(void*, char*)
        void* RTLD_NEXT
    
    cdef extern from "Python.h":
        void Py_Initialize() nogil
    
    cdef extern void initpyshim()
    
    cdef extern int execvp(const char *file, char *const argv[]) nogil: # note nogil here
        Py_Initialize() # initialize Python
        with gil:
            initpyshim() # initialize containing module
            print "Intercepted lookup of %r" % file
            libc_execvp = dlsym(RTLD_NEXT, "execvp")
            if libc_execvp:
                with nogil:
                    return (<int(*)(const char*, char * const *) nogil>libc_execvp)(file, argv)
            return -1
    

    如果您的函数可能被多次调用,您可能希望避免重新初始化您的模块(您可以通过检查Py_IsInitialized() 来做到这一点)。在离开您的方法之前,您可能还需要致电Py_Finalize()

    如果您的目标是 Python 3,则 init 方法称为 PyInit_&lt;modname&gt; 并返回一个 PyObject * 引用,您需要保留该引用直到方法结束(至少)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-26
      • 1970-01-01
      • 2018-06-30
      • 1970-01-01
      • 2017-08-03
      • 1970-01-01
      相关资源
      最近更新 更多