Вызов функции разделяемой библиотеки из Python зависает (возможная проблема потока / прерывания) - PullRequest
0 голосов
/ 11 сентября 2018

У меня проблема с функцией совместно используемой библиотеки, вызываемой из 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;
}

Если я скомпилирую этот код вразделяемая библиотека и вызов myfunction() из программы на C, ссылающейся на нее, все работает как положено .

Однако рассмотрим, что произойдет, если загрузить библиотеку и вызвать myfunction() из Pythonкак это:

from ctypes import *

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

В этом случае программа зависает на неопределенный срок в строке camera_capture() в C-коде.Однако, что-то интересное происходит, посылая KeyboardInterrupt с CTRL+C: непосредственно перед обработкой этого исключения интерпретатором, программа может возобновить работу, и myfunction() продолжается и завершается нормально.

Это похоже назависшая нить.Действительно, запустив вышеуказанный скрипт Python с gdb, я обнаружил, что проприетарный API камеры действительно создает некоторые потоки.И, изучая обратную трассировку, программа застревает при вызове nanosleep() где-то в проприетарном коде.По-видимому, функция nanosleep() не прерывается должным образом, но только при запуске в Python.

Еще один намек на то, что это проблема потока / прерывания, заключается в том, что если я запускаю скрипт Python в gdb,Я могу сделать CTRL+C с последующим continue на неопределенный срок в точке зависания программы.Однако, если я установлю точку останова с b, а затем continue, программа возобновит работу и завершится правильно.

Кто-нибудь знает, что может помешать этой простой программе работать гладко при вызове из Python,и почему потоки, созданные библиотекой C, не завершаются должным образом при запуске из Python?Большое спасибо.

...