属性不存在时PyObject_HasAttrString段错误,存在时不存在



我在Python C API中遇到一个非常奇怪的问题。我有一个包含pyobject"设备"成员的全球范围构造" DCON"。

static status_t get_mac_addr(uint8_t const ** addr, 
                             size_t * const size){
    static uint8_t device_mac_addr[6] = {0};
    *addr = device_mac_addr;
    *size = sizeof device_mac_addr;
    if(PyObject_HasAttrString(dcon.device, "mac_address") == 1){
       ...        
    }
    return 0;
}

看来,每当存在" mac_address"属性时,代码都会很好地执行。奇怪的是,当" mac_address"不是定义的属性时,我会遇到segault( Segmentation fault (core dumped))。这是遇到Segfault时的回溯:

(gdb) bt
#0  0x00000000004ca607 in PyErr_Restore ()
#1  0x00000000004aa29f in PyErr_Format ()
#2  0x000000000049e6ee in _PyObject_GenericGetAttrWithDict ()
#3  0x0000000000486387 in PyObject_GetAttrString ()
#4  0x00000000004ea7d7 in PyObject_HasAttrString ()
#5  0x00007ffff4f2056d in get_mac_addr (size=0x7ffff4f1cd28, addr=<optimized out>) at config.c:165

我和Python C API有点新手。我最初的想法是,我在参考计数方面做错了什么,但是我似乎无法缠绕它。

在多线程应用程序中,任何调用python c api函数的线程都必须首先确保线程持有全局解释器锁定。对于从Python代码调用的函数,这不是问题,因为锁定已持有。

从解释器外部调用的代码不是这种情况(回调等)。

在这种情况下,必须在可以安全地称呼Python API函数之前获取GIL。

PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
...
PyGILState_Release(gstate);

这不仅确保持有GIL,还可以为在Python之外创建的线程创建Python线程状态(使用Direct OS调用,而不是thread.start_new_thread())。

在释放GIL之前,必须处理调用Python API时可能发生的任何Python例外。

请注意,如果另一个线程当前持有锁(例如,因为它正在执行python代码),则确保呼叫将阻止,直到另一个线程释放锁。

,即使已经获取了锁定的锁

相关内容

  • 没有找到相关文章

最新更新