线程异常管理;清空设备队列防止二次释放

This commit is contained in:
gb 2023-11-24 15:38:28 +08:00
parent 9347a4b752
commit f045f7187c
2 changed files with 37 additions and 21 deletions

View File

@ -18,14 +18,14 @@
#pragma comment(lib, "rpcrt4.lib") #pragma comment(lib, "rpcrt4.lib")
#pragma comment(lib, "advapi32.lib") // for Reg... #pragma comment(lib, "advapi32.lib") // for Reg...
#if defined(OEM_NONE) || defined(OEM_LISCHENG) || defined(OEM_HANWANG)|| defined(OEM_ZHONGJING) //#if defined(OEM_NONE) || defined(OEM_LISCHENG) || defined(OEM_HANWANG)|| defined(OEM_ZHONGJING)
#include "../wrapper/hg_log.h" //#include "../wrapper/hg_log.h"
#else //#else
#define VLOG_MINI_1(l, f, d) printf(f, d) //#define utils::to_log(l, f, d) printf(f, d)
#define VLOG_MINI_2(l, f, d1, d2) printf(f, d1, d2) //#define utils::to_log(l, f, d1, d2) printf(f, d1, d2)
#define VLOG_MINI_3(l, f, d1, d2, d3) printf(f, d1, d2, d3) //#define utils::to_log(l, f, d1, d2, d3) printf(f, d1, d2, d3)
#define VLOG_MINI_4(l, f, d1, d2, d3, d4) printf(f, d1, d2, d3, d4) //#define utils::to_log(l, f, d1, d2, d3, d4) printf(f, d1, d2, d3, d4)
#endif //#endif
#include "usbview/enum.h" #include "usbview/enum.h"
#include "../../../sdk/include/huagao/brand.h" #include "../../../sdk/include/huagao/brand.h"
#include <base/utils.h> #include <base/utils.h>
@ -158,7 +158,7 @@ void ovl_mgr::notify_all(void)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// usb_device ... // usb_device ...
usb_device::usb_device(const USBDEV& dev) : ref_(1), udev_(dev), is_ok_(false) usb_device::usb_device(const USBDEV& dev) : ref_(1), udev_(dev), is_ok_(false)
, dev_desc_(NULL), handle_(NULL), online_(true), timout_ms_(1000) , dev_desc_(NULL), handle_(NULL), online_(true), timout_ms_(0)
{ {
memset(&guid_, 0, sizeof(guid_)); memset(&guid_, 0, sizeof(guid_));
} }
@ -353,7 +353,7 @@ bool usb_device::init(void)
clear(); clear();
usb_monitor::enum_usb_device(&usb_monitor::find_parent_hub, &udev_, true); usb_monitor::enum_usb_device(&usb_monitor::find_parent_hub, &udev_, true);
VLOG_MINI_3(LOG_LEVEL_ALL, "Device '%s' at hub '%s + %d'\r\n", udev_.name.c_str(), udev_.hub.c_str(), udev_.port); utils::to_log(LOG_LEVEL_ALL, "Device '%s' at hub '%s + %d'\r\n", udev_.name.c_str(), udev_.hub.c_str(), udev_.port);
if (!udev_.hub.empty()) if (!udev_.hub.empty())
{ {
HANDLE h = CreateFileA(udev_.hub.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); HANDLE h = CreateFileA(udev_.hub.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
@ -553,13 +553,13 @@ int usb_device::open(libusb_device_handle** dev_handle)
root = usb_device::usb_scan_name(udev_.driver_key.c_str());//name使用root时会导致 IO一个异常 root = usb_device::usb_scan_name(udev_.driver_key.c_str());//name使用root时会导致 IO一个异常
if (root.empty()) if (root.empty())
{ {
VLOG_MINI_1(LOG_LEVEL_WARNING, "Cannot find '\\\\.\\Usbscan' name for '%s', try run in Administrator!\r\n", udev_.name.c_str()); utils::to_log(LOG_LEVEL_WARNING, "Cannot find '\\\\.\\Usbscan' name for '%s', try run in Administrator!\r\n", udev_.name.c_str());
root = udev_.name; root = udev_.name;
fmt = "\\%04d"; fmt = "\\%04d";
} }
else else
{ {
VLOG_MINI_2(LOG_LEVEL_WARNING, "Nice: '%s' for '%s'.\r\n", root.c_str(), udev_.name.c_str()); utils::to_log(LOG_LEVEL_WARNING, "Nice: '%s' for '%s'.\r\n", root.c_str(), udev_.name.c_str());
} }
h = open_usb(udev_.name.c_str()); h = open_usb(udev_.name.c_str());
if (h == INVALID_HANDLE_VALUE) if (h == INVALID_HANDLE_VALUE)
@ -673,7 +673,7 @@ int usb_device::transfer_bulk(unsigned endpoint, unsigned char* data, int* lengt
ret = oc->over_lapped()->Internal == STATUS_CANCELLED ? /*LIBUSB_ERROR_TRY_AGAIN*/LIBUSB_ERROR_INTERRUPTED : oc->over_lapped()->Internal; ret = oc->over_lapped()->Internal == STATUS_CANCELLED ? /*LIBUSB_ERROR_TRY_AGAIN*/LIBUSB_ERROR_INTERRUPTED : oc->over_lapped()->Internal;
if (ret == ERROR_NO_MORE_ITEMS) if (ret == ERROR_NO_MORE_ITEMS)
ret = LIBUSB_ERROR_TIMEOUT; ret = LIBUSB_ERROR_TIMEOUT;
VLOG_MINI_2(LOG_LEVEL_WARNING, "Bulk-Transfer of endpoint 0x%02x failed with code 0x%08X\n", endpoint, oc->over_lapped()->Internal); utils::to_log(LOG_LEVEL_WARNING, "Bulk-Transfer of endpoint 0x%02x failed with code 0x%08X\n", endpoint, oc->over_lapped()->Internal);
} }
else else
ret = LIBUSB_SUCCESS; ret = LIBUSB_SUCCESS;
@ -685,11 +685,11 @@ int usb_device::transfer_bulk(unsigned endpoint, unsigned char* data, int* lengt
{ {
if (endpoint & BULKIN_FLAG) if (endpoint & BULKIN_FLAG)
{ {
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Read-bulk = %d, set error as LIBUSB_ERROR_PIPE\r\n", io); utils::to_log(LOG_LEVEL_DEBUG, "Read-bulk = %d, set error as LIBUSB_ERROR_PIPE\r\n", io);
} }
else else
{ {
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Write-bulk = %d, set error as LIBUSB_ERROR_PIPE\r\n", io); utils::to_log(LOG_LEVEL_DEBUG, "Write-bulk = %d, set error as LIBUSB_ERROR_PIPE\r\n", io);
} }
ret = LIBUSB_ERROR_PIPE; ret = LIBUSB_ERROR_PIPE;
} }
@ -785,7 +785,7 @@ int usb_device::transfer_interrupt(unsigned endpoint, unsigned char* data, int*
} }
else else
{ {
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "DeviceIoControl(INT-EP) = %d, set error as LIBUSB_ERROR_PIPE\r\n", io); utils::to_log(LOG_LEVEL_DEBUG, "DeviceIoControl(INT-EP) = %d, set error as LIBUSB_ERROR_PIPE\r\n", io);
ret = LIBUSB_ERROR_PIPE; ret = LIBUSB_ERROR_PIPE;
} }
} }
@ -814,7 +814,15 @@ UINT usb_monitor::find_usb_timer_ = 101;
usb_monitor::usb_monitor() : wnd_monitor_(NULL), handle_msg_id_(0), run_(true) usb_monitor::usb_monitor() : wnd_monitor_(NULL), handle_msg_id_(0), run_(true)
{ {
#ifdef USE_SAFE_THREAD
auto tf = [this](void*) -> void
{
thread_handle_device_change_msg();
};
handle_msg_.start(tf, nullptr, "usb_monitor::thread_handle_device_change_msg");
#else
handle_msg_.reset(new std::thread(&usb_monitor::thread_handle_device_change_msg, this)); handle_msg_.reset(new std::thread(&usb_monitor::thread_handle_device_change_msg, this));
#endif
} }
usb_monitor::~usb_monitor() usb_monitor::~usb_monitor()
{ {
@ -986,7 +994,7 @@ void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive)
{ {
if (devices_[i]->is_online()) if (devices_[i]->is_online())
{ {
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%s is already in device queue and received ARRIVE again, discard this event.\n", dev->name().c_str()); utils::to_log(LOG_LEVEL_DEBUG, "%s is already in device queue and received ARRIVE again, discard this event.\n", dev->name().c_str());
// dev->release(); // dev->release();
return; return;
} }
@ -1035,7 +1043,7 @@ void usb_monitor::notify_usb_event(usb_device*& dev, bool arrive)
} }
if (discard) if (discard)
{ {
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%s is already offline and received LEAVE again, discard this event.\n", dev->name().c_str()); utils::to_log(LOG_LEVEL_DEBUG, "%s is already offline and received LEAVE again, discard this event.\n", dev->name().c_str());
return; return;
} }
} }
@ -1061,7 +1069,7 @@ int usb_monitor::on_usb_pnp(WPARAM wp, LPARAM lp)
if (wp == DBT_DEVICEQUERYREMOVE) if (wp == DBT_DEVICEQUERYREMOVE)
return cur_dev_name_ != utf8; return cur_dev_name_ != utf8;
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "event '%08x' of device %s\n", wp, utf8.c_str()); utils::to_log(LOG_LEVEL_DEBUG, "event '%08x' of device %s\n", wp, utf8.c_str());
int vid = 0, int vid = 0,
pid = 0; pid = 0;
@ -1074,7 +1082,7 @@ int usb_monitor::on_usb_pnp(WPARAM wp, LPARAM lp)
usb_monitor::enum_usb_device(&usb_monitor::usb_dev_by_name, &udev); usb_monitor::enum_usb_device(&usb_monitor::usb_dev_by_name, &udev);
if (wp == DBT_DEVICEARRIVAL && udev.driver_key.empty()) if (wp == DBT_DEVICEARRIVAL && udev.driver_key.empty())
{ {
VLOG_MINI_1(LOG_LEVEL_FATAL, "Failed: driver key for '%s' is not found!\r\n", utf8.c_str()); utils::to_log(LOG_LEVEL_FATAL, "Failed: driver key for '%s' is not found!\r\n", utf8.c_str());
} }
usb_device* ud = new usb_device(udev); usb_device* ud = new usb_device(udev);
@ -1180,7 +1188,7 @@ void usb_monitor::thread_run_device_event_wnd(void)
di.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; di.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
UuidFromStringA((RPC_CSTR)IMAGE_CLASS_GUID, &di.dbcc_classguid); UuidFromStringA((RPC_CSTR)IMAGE_CLASS_GUID, &di.dbcc_classguid);
notify = RegisterDeviceNotificationA(wnd_monitor_, &di, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES); notify = RegisterDeviceNotificationA(wnd_monitor_, &di, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "RegisterDeviceNotificationA = 0x%08x, error = %d. di.dbcc_size = %d\n", notify, GetLastError(), di.dbcc_size); utils::to_log(LOG_LEVEL_DEBUG, "RegisterDeviceNotificationA = 0x%08x, error = %d. di.dbcc_size = %d\n", notify, GetLastError(), di.dbcc_size);
if (!notify) if (!notify)
SetTimer(wnd_monitor_, usb_monitor::find_usb_timer_, 1000, NULL); SetTimer(wnd_monitor_, usb_monitor::find_usb_timer_, 1000, NULL);
} }
@ -1228,6 +1236,7 @@ void usb_monitor::quit(void)
Sleep(100); Sleep(100);
} }
#ifndef USE_SAFE_THREAD
if (handle_msg_.get()) if (handle_msg_.get())
{ {
PostThreadMessageW(handle_msg_id_, WM_QUIT, 0, 0); PostThreadMessageW(handle_msg_id_, WM_QUIT, 0, 0);
@ -1235,11 +1244,13 @@ void usb_monitor::quit(void)
handle_msg_->join(); handle_msg_->join();
handle_msg_.reset(); handle_msg_.reset();
} }
#endif
{ {
std::lock_guard<std::mutex> lock(lock_); std::lock_guard<std::mutex> lock(lock_);
for (auto& v : devices_) for (auto& v : devices_)
v->release(); v->release();
devices_.clear();
} }
} }

View File

@ -13,6 +13,7 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include "libusb-1.0/libusb.h" #include "libusb-1.0/libusb.h"
#include <base/utils.h>
// HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{6bdd1fc6-810f-11d0-bec7-08002be2092f} // HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{6bdd1fc6-810f-11d0-bec7-08002be2092f}
@ -178,7 +179,11 @@ class usb_monitor // consider as libusb_context
std::vector<usb_callback*> cbs_; std::vector<usb_callback*> cbs_;
std::mutex lock_; std::mutex lock_;
std::vector<usb_device*> devices_; std::vector<usb_device*> devices_;
#ifdef USE_SAFE_THREAD
safe_thread handle_msg_;
#else
std::shared_ptr<std::thread> handle_msg_; std::shared_ptr<std::thread> handle_msg_;
#endif
DWORD handle_msg_id_; DWORD handle_msg_id_;
HWND wnd_monitor_; HWND wnd_monitor_;
std::string cur_dev_name_; std::string cur_dev_name_;