当试图从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 ()发布于 2014-04-20 01:28:26
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()。
如果您的目标是Python3,则init方法称为PyInit_<modname>,并返回一个PyObject *引用,您需要将该引用保存到方法的末尾(至少)。
https://stackoverflow.com/questions/23177316
复制相似问题