Skip to content

Commit 009b767

Browse files
committed
usbdmx: Fix use after free hazard in destructor
1 parent 9123824 commit 009b767

File tree

2 files changed

+15
-0
lines changed

2 files changed

+15
-0
lines changed

plugins/usbdmx/AsyncUsbTransceiverBase.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ void AsyncUsbTransceiverBase::TransferCompleteInternal(
6262
m_device_disconnected = true;
6363

6464
TransferComplete(transfer);
65+
66+
{
67+
ola::thread::MutexLocker locker(&m_mutex);
68+
if (m_inflight.empty())
69+
m_cond.Signal();
70+
}
6571
}
6672

6773
AsyncUsbTransceiverBase::AsyncUsbTransceiverBase(LibUsbAdaptor *adaptor,
@@ -83,6 +89,14 @@ AsyncUsbTransceiverBase::~AsyncUsbTransceiverBase() {
8389

8490
CancelTransfer();
8591

92+
while (!m_inflight.empty()) {
93+
/* Wait for cancelled transfers to complete, freeing the transfers
94+
* below before the callbacks happen is undefined behaviour according
95+
* to libusb docs. Here's to hoping this destructor runs in a different
96+
* thread than the one processing libusb callbacks. */
97+
m_cond.Wait(&m_mutex);
98+
}
99+
86100
m_adaptor->UnrefDevice(m_usb_device);
87101

88102
while (!m_idle.empty()) {

plugins/usbdmx/AsyncUsbTransceiverBase.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ class AsyncUsbTransceiverBase {
134134
std::queue<struct libusb_transfer*> m_idle; // GUARDED_BY(m_mutex);
135135

136136
ola::thread::Mutex m_mutex;
137+
ola::thread::ConditionVariable m_cond;
137138

138139
private:
139140
/**

0 commit comments

Comments
 (0)