从Python调用共享库函数会挂起(可能发生线程/中断问题)

时间:2018-09-11 16:41:52

标签: python multithreading shared-libraries deadlock ctypes

我有一个从Python调用的共享库函数的问题。

考虑以下简化的C程序,该程序可从相机获取图像:

#include <stdio.h>

#include <someproprietarylibraryheader.h>

int myfunction() {
    CameraHandle handle;

    printf("Running... \n");

    if(!camera_init(&handle) {     // initialize the camera handle
        return -1;
    }

    if(!camera_precapture(handle)) {   // prepare for capture
        printf("ERROR precapture\n");
        return -1;
    }
    else {
        printf("precapture OK\n");
    }

    if(!camera_capture(handle)) {  // start frame capture (returns immediately)
        printf("ERROR capture\n");
        return -1;
    }
    else {
        printf("capture OK\n");
    }

    if(!camera_wait(handle)) {     // wait for capture to be completed   
        printf("ERROR wait\n");
        return -1;
    }
    else {
        printf("wait OK\n");
    }

    if(!camera_close(handle)) {    // close the camera
        printf("ERROR close\n");
        return -1;
    }

    printf("Done!!\n");

    return 0;
}

如果我将此代码编译到共享库中,并从链接到它的C程序中调用myfunction(),则一切正常。

但是,请考虑一下,如果这样加载了libray并从Python调用myfunction()会发生什么情况:

from ctypes import *

mylib = cdll.LoadLibrary("mylib.so")
mylib.myfunction()

在这种情况下,程序会无限期地挂在C代码中的行camera_capture()上。但是,通过发送带有KeyboardInterrupt的{​​{1}}会发生一些有趣的事情:在解释器处理此异常之前,程序可以继续运行,CTRL+C可以继续正常终止。

这看起来像是挂线。实际上,通过使用myfunction()运行上述Python脚本,我发现专有的相机API确实创建了一些线程。通过检查回溯,该程序似乎停留在专有代码内某个地方对gdb的调用上。显然,nanosleep()函数没有被正确中断,只有在Python中运行时才被中断。

另一个暗示这是线程/中断问题的事实是,如果我在nanosleep()中运行Python脚本,则可以无限期地执行gdb,然后执行CTRL+C程序挂起。但是,如果我先用continue然后再用b设置断点,程序将继续执行并正确终止。

有人知道什么可能导致从Python调用此简单程序时无法顺利运行,为什么从Python运行时C库创建的线程不能正确终止?非常感谢。

0 个答案:

没有答案