Index: device/usb/usb_device_handle_usbfs.cc |
diff --git a/device/usb/usb_device_handle_usbfs.cc b/device/usb/usb_device_handle_usbfs.cc |
index d168e2f4daa0187bd117995c9671a07a96ad0c52..37b3bb1c132ae53ffd268fc497f5e484d9b1d5a1 100644 |
--- a/device/usb/usb_device_handle_usbfs.cc |
+++ b/device/usb/usb_device_handle_usbfs.cc |
@@ -423,22 +423,27 @@ UsbDeviceHandleUsbfs::UsbDeviceHandleUsbfs( |
} |
scoped_refptr<UsbDevice> UsbDeviceHandleUsbfs::GetDevice() const { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
return device_; |
} |
void UsbDeviceHandleUsbfs::Close() { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
if (!device_) |
return; // Already closed. |
+ // Cancelling transfers may run or destroy callbacks holding the last |
+ // reference to this object so hold a reference for the rest of this method. |
+ scoped_refptr<UsbDeviceHandleUsbfs> self(this); |
+ for (const auto& transfer : transfers_) |
+ CancelTransfer(transfer.get(), UsbTransferStatus::CANCELLED); |
+ |
// On the |task_runner_| thread check |device_| to see if the handle is |
// closed. On the |blocking_task_runner_| thread check |fd_.is_valid()| to |
// see if the handle is closed. |
device_->HandleClosed(this); |
device_ = nullptr; |
- for (const auto& transfer : transfers_) |
- CancelTransfer(transfer.get(), UsbTransferStatus::CANCELLED); |
- |
// Releases |helper_|. |
blocking_task_runner_->PostTask( |
FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::CloseBlocking, this)); |
@@ -446,6 +451,7 @@ void UsbDeviceHandleUsbfs::Close() { |
void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value, |
const ResultCallback& callback) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
if (!device_) { |
task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
return; |
@@ -463,6 +469,7 @@ void UsbDeviceHandleUsbfs::SetConfiguration(int configuration_value, |
void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number, |
const ResultCallback& callback) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
if (!device_) { |
task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
return; |
@@ -487,6 +494,7 @@ void UsbDeviceHandleUsbfs::ClaimInterface(int interface_number, |
void UsbDeviceHandleUsbfs::ReleaseInterface(int interface_number, |
const ResultCallback& callback) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
if (!device_) { |
task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
return; |
@@ -505,6 +513,7 @@ void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting( |
int interface_number, |
int alternate_setting, |
const ResultCallback& callback) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
if (!device_) { |
task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
return; |
@@ -521,6 +530,7 @@ void UsbDeviceHandleUsbfs::SetInterfaceAlternateSetting( |
} |
void UsbDeviceHandleUsbfs::ResetDevice(const ResultCallback& callback) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
if (!device_) { |
task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
return; |
@@ -537,6 +547,7 @@ void UsbDeviceHandleUsbfs::ResetDevice(const ResultCallback& callback) { |
void UsbDeviceHandleUsbfs::ClearHalt(uint8_t endpoint_address, |
const ResultCallback& callback) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
if (!device_) { |
task_runner_->PostTask(FROM_HERE, base::Bind(callback, false)); |
return; |
@@ -562,6 +573,7 @@ void UsbDeviceHandleUsbfs::ControlTransfer( |
size_t length, |
unsigned int timeout, |
const TransferCallback& callback) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
if (!device_) { |
task_runner_->PostTask( |
FROM_HERE, |
@@ -598,6 +610,7 @@ void UsbDeviceHandleUsbfs::IsochronousTransferIn( |
const std::vector<uint32_t>& packet_lengths, |
unsigned int timeout, |
const IsochronousTransferCallback& callback) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
uint8_t endpoint_address = USB_DIR_IN | endpoint_number; |
size_t total_length = |
std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u); |
@@ -612,6 +625,7 @@ void UsbDeviceHandleUsbfs::IsochronousTransferOut( |
const std::vector<uint32_t>& packet_lengths, |
unsigned int timeout, |
const IsochronousTransferCallback& callback) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
uint8_t endpoint_address = USB_DIR_OUT | endpoint_number; |
size_t total_length = |
std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u); |
@@ -639,6 +653,7 @@ void UsbDeviceHandleUsbfs::GenericTransfer(UsbTransferDirection direction, |
const UsbInterfaceDescriptor* UsbDeviceHandleUsbfs::FindInterfaceByEndpoint( |
uint8_t endpoint_address) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
auto it = endpoints_.find(endpoint_address); |
if (it != endpoints_.end()) |
return it->second.interface; |
@@ -664,6 +679,7 @@ void UsbDeviceHandleUsbfs::SetConfigurationComplete( |
int configuration_value, |
bool success, |
const ResultCallback& callback) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
if (success && device_) { |
device_->ActiveConfigurationChanged(configuration_value); |
// TODO(reillyg): If all interfaces are unclaimed before a new configuration |
@@ -676,6 +692,7 @@ void UsbDeviceHandleUsbfs::SetConfigurationComplete( |
void UsbDeviceHandleUsbfs::ReleaseInterfaceComplete( |
int interface_number, |
const ResultCallback& callback) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
auto it = interfaces_.find(interface_number); |
DCHECK(it != interfaces_.end()); |
interfaces_.erase(it); |
@@ -690,6 +707,7 @@ void UsbDeviceHandleUsbfs::IsochronousTransferInternal( |
const std::vector<uint32_t>& packet_lengths, |
unsigned int timeout, |
const IsochronousTransferCallback& callback) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
if (!device_) { |
ReportIsochronousError(packet_lengths, callback, |
UsbTransferStatus::DISCONNECT); |
@@ -737,6 +755,7 @@ void UsbDeviceHandleUsbfs::GenericTransferInternal( |
unsigned int timeout, |
const TransferCallback& callback, |
scoped_refptr<base::SingleThreadTaskRunner> callback_runner) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
if (!device_) { |
callback_runner->PostTask( |
FROM_HERE, |
@@ -779,6 +798,7 @@ void UsbDeviceHandleUsbfs::GenericTransferInternal( |
} |
void UsbDeviceHandleUsbfs::ReapedUrbs(const std::vector<usbdevfs_urb*>& urbs) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
for (auto* urb : urbs) { |
Transfer* transfer = static_cast<Transfer*>(urb->usercontext); |
DCHECK_EQ(urb, &transfer->urb); |
@@ -795,6 +815,7 @@ void UsbDeviceHandleUsbfs::ReapedUrbs(const std::vector<usbdevfs_urb*>& urbs) { |
void UsbDeviceHandleUsbfs::TransferComplete( |
std::unique_ptr<Transfer> transfer) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
if (transfer->cancelled) |
return; |
@@ -829,6 +850,7 @@ void UsbDeviceHandleUsbfs::TransferComplete( |
} |
void UsbDeviceHandleUsbfs::RefreshEndpointInfo() { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
endpoints_.clear(); |
const UsbConfigDescriptor* config = device_->active_configuration(); |
@@ -858,6 +880,7 @@ void UsbDeviceHandleUsbfs::ReportIsochronousError( |
const std::vector<uint32_t>& packet_lengths, |
const UsbDeviceHandle::IsochronousTransferCallback& callback, |
UsbTransferStatus status) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
std::vector<UsbDeviceHandle::IsochronousPacket> packets( |
packet_lengths.size()); |
for (size_t i = 0; i < packet_lengths.size(); ++i) { |
@@ -870,18 +893,23 @@ void UsbDeviceHandleUsbfs::ReportIsochronousError( |
void UsbDeviceHandleUsbfs::SetUpTimeoutCallback(Transfer* transfer, |
unsigned int timeout) { |
- if (timeout > 0) { |
- transfer->timeout_closure.Reset( |
- base::Bind(&UsbDeviceHandleUsbfs::CancelTransfer, this, transfer, |
- UsbTransferStatus::TIMEOUT)); |
- task_runner_->PostDelayedTask(FROM_HERE, |
- transfer->timeout_closure.callback(), |
- base::TimeDelta::FromMilliseconds(timeout)); |
- } |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
+ if (timeout == 0) |
+ return; |
+ |
+ transfer->timeout_closure.Reset( |
+ base::Bind(&UsbDeviceHandleUsbfs::OnTimeout, this, transfer)); |
+ task_runner_->PostDelayedTask(FROM_HERE, transfer->timeout_closure.callback(), |
+ base::TimeDelta::FromMilliseconds(timeout)); |
+} |
+ |
+void UsbDeviceHandleUsbfs::OnTimeout(Transfer* transfer) { |
+ CancelTransfer(transfer, UsbTransferStatus::TIMEOUT); |
} |
std::unique_ptr<UsbDeviceHandleUsbfs::Transfer> |
UsbDeviceHandleUsbfs::RemoveFromTransferList(Transfer* transfer_ptr) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
auto it = std::find_if( |
transfers_.begin(), transfers_.end(), |
[transfer_ptr](const std::unique_ptr<Transfer>& transfer) -> bool { |
@@ -895,12 +923,22 @@ UsbDeviceHandleUsbfs::RemoveFromTransferList(Transfer* transfer_ptr) { |
void UsbDeviceHandleUsbfs::CancelTransfer(Transfer* transfer, |
UsbTransferStatus status) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
+ DCHECK(device_); |
+ |
if (transfer->cancelled) |
return; |
// |transfer| must stay in |transfers_| as it is still being processed by the |
// kernel and will be reaped later. |
transfer->cancelled = true; |
+ |
+ blocking_task_runner_->PostTask( |
+ FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::DiscardUrb, |
+ base::Unretained(helper_.get()), transfer)); |
+ |
+ // Cancelling |timeout_closure| and running completion callbacks may free |
+ // |this| so these operations must be performed at the end of this function. |
transfer->timeout_closure.Cancel(); |
if (transfer->urb.type == USBDEVFS_URB_TYPE_ISO) { |
@@ -914,14 +952,10 @@ void UsbDeviceHandleUsbfs::CancelTransfer(Transfer* transfer, |
} else { |
transfer->RunCallback(status, 0); |
} |
- |
- blocking_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&UsbDeviceHandleUsbfs::FileThreadHelper::DiscardUrb, |
- base::Unretained(helper_.get()), transfer)); |
} |
- |
void UsbDeviceHandleUsbfs::UrbDiscarded(Transfer* transfer) { |
+ DCHECK(sequence_checker_.CalledOnValidSequence()); |
transfer->discarded = true; |
if (transfer->reaped) |
RemoveFromTransferList(transfer); |