USB: Destroy the default pipe last, and put our ID before it.

If we don't, then new transfers could still be queued even after
we've put its USB ID, since it's usually accessed via Device.

May further help with #19180.
This commit is contained in:
Augustin Cavalier 2024-10-17 16:04:27 -04:00
parent e3dc9757d2
commit 8e300ef227

View File

@ -329,18 +329,6 @@ Device::Device(Object* parent, int8 hubAddress, uint8 hubPort,
Device::~Device()
{
// Cancel transfers on the default pipe and put its USBID to prevent
// further transfers from being queued.
if (fDefaultPipe != NULL) {
fDefaultPipe->PutUSBID(false);
fDefaultPipe->CancelQueuedTransfers(true);
fDefaultPipe->WaitForIdle();
}
// Destroy open endpoints. Do not send a device request to unconfigure
// though, since we may be deleted because the device was unplugged already.
Unconfigure(false);
if (fNode != NULL) {
status_t error = gDeviceManager->unregister_node(fNode);
if (error != B_OK && error != B_BUSY)
@ -348,6 +336,10 @@ Device::~Device()
fNode = NULL;
}
// Destroy open endpoints. Do not send a device request to unconfigure
// though, since we may be deleted because the device was unplugged already.
Unconfigure(false);
// Destroy all Interfaces in the Configurations hierarchy.
for (int32 i = 0; fConfigurations != NULL
&& i < fDeviceDescriptor.num_configurations; i++) {
@ -364,16 +356,28 @@ Device::~Device()
usb_interface_info* interface = &interfaceList->alt[k];
Interface* interfaceObject =
(Interface*)GetStack()->GetObject(interface->handle);
interface->handle = 0;
if (interfaceObject != NULL)
interfaceObject->ReleaseReference();
delete interfaceObject;
interface->handle = 0;
}
}
}
// Remove ourselves from the stack before deleting public structures.
PutUSBID();
if (fDefaultPipe != NULL) {
fDefaultPipe->PutUSBID(false);
// Also put our ID to prevent further transfers on the default pipe
// from being queued. (We have to do this after putting the pipe's ID,
// since we are its parent.)
PutUSBID(false);
fDefaultPipe->CancelQueuedTransfers(true);
fDefaultPipe->WaitForIdle();
}
// Ensure we are gone from the stack before deleting public structures.
PutUSBID(true);
delete fDefaultPipe;
if (fConfigurations == NULL) {