diff --git a/src/add-ons/kernel/network/stack/interfaces.cpp b/src/add-ons/kernel/network/stack/interfaces.cpp index 60e4a0175c..8921092aa3 100644 --- a/src/add-ons/kernel/network/stack/interfaces.cpp +++ b/src/add-ons/kernel/network/stack/interfaces.cpp @@ -1426,11 +1426,16 @@ get_interface(net_domain* domain, uint32 index) if (interface == NULL || interface->IsBusy()) return NULL; + // We must unlock before invoking CreateDomainDatalinkIfNeeded, because + // otherwise we can hit lock ordering inversions with receive threads, + // usually in register_device_handler. + BReference interfaceRef(interface); + locker.Unlock(); + if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) return NULL; - interface->AcquireReference(); - return interface; + return interfaceRef.Detach(); } @@ -1443,11 +1448,14 @@ get_interface(net_domain* domain, const char* name) if (interface == NULL || interface->IsBusy()) return NULL; + // See comment in get_interface. + BReference interfaceRef(interface); + locker.Unlock(); + if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) return NULL; - interface->AcquireReference(); - return interface; + return interfaceRef.Detach(); } @@ -1461,11 +1469,15 @@ get_interface_for_device(net_domain* domain, uint32 index) if (interface->device->index == index) { if (interface->IsBusy()) return NULL; + + // See comment in get_interface. + BReference interfaceRef(interface); + locker.Unlock(); + if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) return NULL; - interface->AcquireReference(); - return interface; + return interfaceRef.Detach(); } } @@ -1499,11 +1511,15 @@ get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress) && linkAddress.sdl_index == interface->index)) { if (interface->IsBusy()) return NULL; + + // See comment in get_interface. + BReference interfaceRef(interface); + locker.Unlock(); + if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) return NULL; - interface->AcquireReference(); - return interface; + return interfaceRef.Detach(); } }