简体   繁体   English

使用C ++ 11异步时Libusb挂起

[英]Libusb hangs when using C++11 async

I'm new to libusb, so I don't really understand it very well. 我是libusb的新手,所以我不太了解它。 I'm trying to do some USB communication. 我正在尝试进行一些USB通信。

I'm using the hotplug feature which works quite well. 我正在使用效果很好的热插拔功能。 So I thought when I detect a device arrived event, I would do all communication with USB on another thread using the C++11 asynchronous feature, so I could do synchronous I/O with multiple devices to simply codes. 因此,我想当我检测到设备到达事件时,我将使用C ++ 11异步功能通过另一个线程与USB进行所有通信,因此我可以对多个设备进行同步I / O,以进行简单的编码。 Their asynchronous I/O is a bit confusing to me. 他们的异步I / O使我有些困惑。 Hopefully I can use the synchronous I/O with C++ asynchronous feature. 希望我可以将同步I / O与C ++异步功能一起使用。

But I'm having a problem where some libusb call seem to hang when the code is running in C++11 asynchronous feature. 但是我有一个问题,当代码以C ++ 11异步功能运行时,某些libusb调用似乎挂起。 When it is not running in C++11 asynchronous feature it works without any problem. 当它不在C ++ 11异步功能中运行时,它可以正常工作。

So I'm assuming it is my C++11 asynchronous feature code that's the problem. 所以我假设这是我的C ++ 11异步功能代码。

Here is my hotplug callback: 这是我的热插拔回调:

int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
  std::future<void> result(std::async([] (libusb_device *d) {

    libusb_device_handle *h;

    printf("%s\n", "Opening");
    int rc = libusb_open(d, &h);
    if(rc != LIBUSB_SUCCESS) {
      printf("ERROR: %s\n", libusb_error_name(rc));
      return;
    }
    printf("%s\n", "Opened");

    printf("%s\n", "Closing");
    libusb_close(h);
    printf("%s\n", "Closed!");

  }, dev));

  result.get();

  return 0;
}

So with this code it hangs on libusb_close 所以用这段代码挂在libusb_close

It outputs: 它输出:

Opening
Opened
Closing

The main code looks like this: 主要代码如下:

int main(int argc, char* argv[]) {

  int vendor_id = 0x1234;
  int product_id = 0x4556;

  libusb_hotplug_callback_handle *hp = nullptr;
  libusb_context *context = nullptr;
  int rc = libusb_init(&context);

  if(rc < 0)
  {
    return rc;
  }

  libusb_set_debug(context, LIBUSB_LOG_LEVEL_WARNING);

  rc = libusb_hotplug_register_callback(
    context,
    LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
    LIBUSB_HOTPLUG_NO_FLAGS,
    vendor_id,
    product_id,
    LIBUSB_HOTPLUG_MATCH_ANY,
    hotplug_callback,
    NULL,
    hp
    );

  if (LIBUSB_SUCCESS != rc) {
    libusb_exit (context);
    return rc;
  }

  while(1) {
    rc = libusb_handle_events(context);
  }

  return 0;
}

Mind you this code is more prototypical, so it is not really well written. 请注意,此代码更具原型性,因此编写得并不好。 It is still in the exploration mode of libusb. 它仍处于libusb的探索模式。

According to their own website , using multi-threading with libusb (and std::async is essentially multi-threading if it isn't serialised) requires quite some considerations. 根据他们自己的网站 ,使用libusb多线程(如果未序列化std::async本质上就是多线程),则需要考虑很多因素。

For example, they specifically state: 例如,他们特别声明:

libusb_close() will remove a file descriptor from the poll set. libusb_close()将从轮询集中删除文件描述符。 There are all kinds of race conditions that could arise here, so it is important that nobody is doing event handling at this time. 这里可能会出现各种各样的竞争情况,因此,此时没有人要进行事件处理非常重要。

In your code, there is no synchronisation between the call to libusb_close in the one thread and libusb_handle_events in the other. 在您的代码中,在一个线程中对libusb_close的调用与在另一个线程中的libusb_handle_events的调用之间没有同步。 Related (from the same source as above): 相关(与上述来源相同):

The issue is that if two or more threads are concurrently calling poll() or select() on libusb's file descriptors then only one of those threads will be woken up when an event arrives. 问题是,如果两个或多个线程同时在libusb的文件描述符上调用poll()或select(),则事件到达时只会唤醒其中一个线程。 The others will be completely oblivious that anything has happened. 其他人将完全忽略发生任何事情。

It is entirely imaginable that what happens here is that libusb_handle_events in the main thread is "stealing" an event that libusb_close is waiting for, making it never return. 完全可以想象,这里发生的是主线程中的libusb_handle_events正在“窃取” libusb_close正在等待的事件,从而使其永不返回。

The bottom line is that you need to either: 底线是您需要:

  1. follow the linked article, which explains in detail how to use libusb with multi-threading, or 遵循链接的文章,该文章详细说明了如何在多线程中使用libusb,或者
  2. understand the asynchronous API of libusb and make use of that instead. 了解libusb的异步API并改用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM