libudev странное поведение v1.7.2 и выше

Я столкнулся с определенной проблемой с libudev. Я написал поток прослушивателя, который постоянно прослушивает устройства, подключенные через usb. Я использовал API libudev udev_monitor_receive_device в начале непрерывного цикла while, так как это блокирующий вызов. Исходный код отлично работает с libudev v1.6.3, но при обновлении до v1.7.2 вызов udev_monitor_receive_device больше не блокируется, цикл while продолжает работать непрерывно, а API продолжает возвращать NULL. Ниже приведен фрагмент кода, который поможет вам понять использование libudev в моем коде.

struct udev *udevObject ;
struct udev_device *mDev;
struct udev_enumerate *enumerate;
struct udev_monitor *mUdevMonitorObject;

udevObject = udev_new();
if(NULL == udevObject){
    LOGERR((TEXT("Listener thread :: Error initialising Udev Library\r\n")));
    return false;
}
mUdevMonitorObject = udev_monitor_new_from_netlink(udevObject, "udev");
udev_monitor_enable_receiving(mUdevMonitorObject);
//    enumerate = udev_enumerate_new(udevObject);
//    udev_enumerate_scan_devices(enumerate);


while(1)
{
    // This loop keeps running continuously on libudev v1.7.3, but the call blocks for v1.6.3
    mDev = udev_monitor_receive_device(mUdevMonitorObject);
    LOGINFO((TEXT("Listener thread:: Processing UDEV trigger\r\n")));
}

Эта проблема мучает меня давно. Любая помощь будет оценена по достоинству.


person Manish Narang    schedule 07.12.2011    source источник
comment
Вы проверили документацию, чтобы API или его поведение не изменились? В противном случае это может быть ошибка, и ее следует направлять разработчикам libudev, а не SO.   -  person Some programmer dude    schedule 07.12.2011


Ответы (2)


Да, я вижу то же самое. Кажется, единственный способ взаимодействовать с udev_monitor_receive_device в наши дни — это select/poll — у меня есть аналогичный цикл, и добавление этих строк перед udev_monitor_receive_device делает все разумным:

int fd = udev_monitor_get_fd(mUdevMonitorObject);
fd_set fdset;
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
if(select(fd+1, &fdset, NULL, NULL, NULL) < 0) {
    /* error in select */
    continue;
}

Было бы неплохо, если бы receive_device все еще блокировался, пока не будут готовы данные, вместо того, чтобы заставлять вас танцевать, но вот так.

person sqweek    schedule 25.06.2012

См. справочник по API:

Сокет монитора по умолчанию настроен на НЕБЛОКИРОВКУ. Вариант poll() для файлового дескриптора, возвращаемого udev_monitor_get_fd(), следует использовать для пробуждения при появлении новых устройств или, в качестве альтернативы, файловый дескриптор переключается в режим блокировки.

person Lars    schedule 08.01.2014