hrev51071 adds 1 changeset to branch 'master'
old head: ceff2b88ae26f78af0f954d8836ab50765ff7733
new head: f17488662a661029abeba1594c92904f7670c406
overview:
http://cgit.haiku-os.org/haiku/log/?qt=range&q=f17488662a66+%5Eceff2b88ae26
----------------------------------------------------------------------------
f17488662a66: network stack: Fixed double mutex lock.
* device_removed() no longer uses get_device_interface() to avoid
the double locking.
* Introduced net_device_interface::busy member to avoid locking in
device_removed() for too long.
* This should fix #7252.
[ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]
----------------------------------------------------------------------------
Revision: hrev51071
Commit: f17488662a661029abeba1594c92904f7670c406
URL: http://cgit.haiku-os.org/haiku/commit/?id=f17488662a66
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Thu Apr 6 16:14:52 2017 UTC
Ticket: https://dev.haiku-os.org/ticket/7252
----------------------------------------------------------------------------
2 files changed, 23 insertions(+), 7 deletions(-)
.../kernel/network/stack/device_interfaces.cpp | 25 ++++++++++++++++----
.../kernel/network/stack/device_interfaces.h | 5 ++--
----------------------------------------------------------------------------
diff --git a/src/add-ons/kernel/network/stack/device_interfaces.cpp
b/src/add-ons/kernel/network/stack/device_interfaces.cpp
index 0143360..27dc784 100644
--- a/src/add-ons/kernel/network/stack/device_interfaces.cpp
+++ b/src/add-ons/kernel/network/stack/device_interfaces.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
+ * Copyright 2006-2017, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -152,6 +152,7 @@ domain_receive_adapter(void* cookie, net_device* device,
net_buffer* buffer)
static net_device_interface*
find_device_interface(const char* name)
{
+ ASSERT_LOCKED_MUTEX(&sLock);
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
while (net_device_interface* interface = iterator.Next()) {
@@ -182,6 +183,7 @@ allocate_device_interface(net_device* device,
net_device_module_info* module)
interface->device = device;
interface->up_count = 0;
interface->ref_count = 1;
+ interface->busy = false;
interface->monitor_count = 0;
interface->deframe_func = NULL;
interface->deframe_ref_count = 0;
@@ -409,6 +411,9 @@ get_device_interface(uint32 index)
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
while (net_device_interface* interface = iterator.Next()) {
if (interface->device->index == index) {
+ if (interface->busy)
+ break;
+
if (atomic_add(&interface->ref_count, 1) != 0)
return interface;
}
@@ -428,6 +433,9 @@ get_device_interface(const char* name, bool create)
net_device_interface* interface = find_device_interface(name);
if (interface != NULL) {
+ if (interface->busy)
+ return NULL;
+
if (atomic_add(&interface->ref_count, 1) != 0)
return interface;
@@ -763,11 +771,17 @@ device_removed(net_device* device)
{
MutexLocker locker(sLock);
- // hold a reference to the device interface being removed
- // so our put_() will (eventually) do the final cleanup
- net_device_interface* interface = get_device_interface(device->name,
false);
+ net_device_interface* interface = find_device_interface(device->name);
if (interface == NULL)
return B_DEVICE_NOT_FOUND;
+ if (interface->busy)
+ return B_BUSY;
+
+ // Acquire a reference to the device interface being removed
+ // so our put_() will (eventually) do the final cleanup
+ atomic_add(&interface->ref_count, 1);
+ interface->busy = true;
+ locker.Unlock();
// Propagate the loss of the device throughout the stack.
@@ -776,8 +790,9 @@ device_removed(net_device* device)
// By now all of the monitors must have removed themselves. If they
// didn't, they'll probably wait forever to be callback'ed again.
- recursive_lock_lock(&interface->monitor_lock);
+ RecursiveLocker monitorLocker(interface->monitor_lock);
interface->monitor_funcs.RemoveAll();
+ monitorLocker.Unlock();
// All of the readers should be gone as well since we are out of
// interfaces and put_domain_datalink_protocols() is called for
diff --git a/src/add-ons/kernel/network/stack/device_interfaces.h
b/src/add-ons/kernel/network/stack/device_interfaces.h
index 958448e..fef47f5 100644
--- a/src/add-ons/kernel/network/stack/device_interfaces.h
+++ b/src/add-ons/kernel/network/stack/device_interfaces.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
+ * Copyright 2006-2017, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -32,12 +32,13 @@ struct net_device_interface :
DoublyLinkedListLinkImpl<net_device_interface> {
uint32 up_count;
// a device can be brought up by more than one interface
int32 ref_count;
+ bool busy;
net_deframe_func deframe_func;
int32 deframe_ref_count;
int32 monitor_count;
- recursive_lock monitor_lock;
+ recursive_lock monitor_lock;
DeviceMonitorList monitor_funcs;
DeviceHandlerList receive_funcs;