Libusb在使用c++ 11 async时挂起
Libusb hangs when using C++11 async
我是libusb的新手,所以我不是很了解它。我正在尝试做一些USB通信。
我正在使用热插拔功能,它工作得很好。所以我想当我检测到设备到达事件时,我会使用c++ 11异步功能在另一个线程上与USB进行所有通信,这样我就可以对多个设备进行同步I/O以简单地编码。它们的异步I/O让我有点困惑。希望我可以使用同步I/O与c++的异步特性。
但是我有一个问题,当代码在c++ 11异步特性中运行时,一些libusb调用似乎挂起了。当它不运行在c++ 11异步特性,它工作没有任何问题。
所以我假设这是我的c++ 11异步特性代码的问题。
这是我的热插拔回调:
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("%sn", "Opening");
int rc = libusb_open(d, &h);
if(rc != LIBUSB_SUCCESS) {
printf("ERROR: %sn", libusb_error_name(rc));
return;
}
printf("%sn", "Opened");
printf("%sn", "Closing");
libusb_close(h);
printf("%sn", "Closed!");
}, dev));
result.get();
return 0;
}
所以这个代码挂在libusb_close
输出:
Opening
Opened
Closing
主代码如下:
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;
}
请注意,这段代码比较原型化,所以写得不是很好。目前还处于libusb的探索模式
根据他们自己的网站,在libusb中使用多线程(如果没有序列化,std::async
本质上是多线程的)需要相当多的考虑。
例如,它们特别声明:
libusb_close()将从轮询集中删除一个文件描述符。这里可能会出现各种竞态条件,因此此时没有人进行事件处理是很重要的。
在您的代码中,在一个线程中调用libusb_close
和在另一个线程中调用libusb_handle_events
之间没有同步。相关(来源与上述相同):
问题是,如果两个或多个线程并发地调用libusb文件描述符上的poll()或select(),那么当事件到达时,这些线程中只有一个会被唤醒。其他人会完全忘记发生了什么。
完全可以想象,这里发生的事情是主线程中的libusb_handle_events
正在"窃取"libusb_close
正在等待的事件,使其永远不会返回。
底线是你需要:
- 查看链接的文章,该文章详细解释了如何将libusb与多线程一起使用,或者
- 了解libbusb的异步API并使用它。
- 挂起和取消挂起一个文件DLL
- 如何防止C++遗留代码中的挂起指针
- 为什么所有C++编译器都会崩溃或挂起此代码
- 我编写了代码将十进制分数转换为其二进制等效数.它编译得很好,但在执行时挂起
- 构建挂起,即使是适度的文件大小
- 循环挂起迭代的 std::擦除 on std::list
- Poco::Net::FTPClientSession 在 open() 方法上挂起 129 秒,如果 ftp 主机不存
- Node.js fs.open() 在尝试打开 4 个以上的命名管道 (FIFO) 后挂起
- 从不同进程中的另一个线程挂起/恢复线程或进程
- Boost (Beast) websocket:同步写入挂起
- 为什么析构函数挂起
- 使用互斥会挂起程序
- 在C++和 Python 程序中使用命名管道的 IPC 挂起
- 设置变量时C++程序挂起
- 第一次尝试使用new动态创建结构数组,程序挂起没有错误
- 从stdin读取时子进程挂起(fork/dup2竞争条件)
- 有时ShowWindow从不调用OnShowWindow,主应用程序挂起
- 如何防止GUI挂起,同时允许第二次操作与Qt中的第一次操作一起执行
- std::future从std::async返回,在超出范围时挂起
- Libusb在使用c++ 11 async时挂起