[haiku-commits] r38118 - haiku/trunk/src/add-ons/kernel/network/stack

Author: axeld
Date: 2010-08-15 15:21:42 +0200 (Sun, 15 Aug 2010)
New Revision: 38118
Changeset: http://dev.haiku-os.org/changeset/38118
Ticket: http://dev.haiku-os.org/ticket/6446

Modified:
   haiku/trunk/src/add-ons/kernel/network/stack/datalink.cpp
   haiku/trunk/src/add-ons/kernel/network/stack/device_interfaces.cpp
Log:
* Spotted a few reference counting bugs that were probably responsible for
  #6446, although I could not reproduce the exact problem.
* net_datalink::is_local_[link_]address() now releases a previous reference if
  the _interfaceAddress arguments does not point to NULL.
* When a buffer is received from a device, it's interface_address should be NULL
  already.


Modified: haiku/trunk/src/add-ons/kernel/network/stack/datalink.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/network/stack/datalink.cpp   2010-08-15 
13:17:52 UTC (rev 38117)
+++ haiku/trunk/src/add-ons/kernel/network/stack/datalink.cpp   2010-08-15 
13:21:42 UTC (rev 38118)
@@ -164,7 +164,17 @@
 }
 
 
-status_t
+static void
+set_interface_address(net_interface_address*& target, InterfaceAddress* 
address)
+{
+       if (target != NULL)
+               static_cast<InterfaceAddress*>(target)->ReleaseReference();
+
+       target = address;
+}
+
+
+static status_t
 fill_address(const sockaddr* from, sockaddr* to, size_t maxLength)
 {
        if (from != NULL) {
@@ -260,7 +270,7 @@
 
                        return status;
                }
-       
+
                case SIOCGIFCOUNT:
                {
                        // count number of interfaces
@@ -340,7 +350,7 @@
 {
        TRACE("%s(route %p, buffer %p)\n", __FUNCTION__, route, buffer);
 
-       net_interface_address* address = route->interface_address;
+       InterfaceAddress* address = (InterfaceAddress*)route->interface_address;
        Interface* interface = (Interface*)address->interface;
 
        //dprintf("send buffer (%ld bytes) to interface %s (route flags %lx)\n",
@@ -356,7 +366,8 @@
 
                // We set the interface address here, so the buffer is delivered
                // directly to the domain in 
interfaces.cpp:device_consumer_thread()
-               buffer->interface_address = address;
+               address->AcquireReference();
+               set_interface_address(buffer->interface_address, address);
 
                // this one goes back to the domain directly
                return fifo_enqueue_buffer(
@@ -408,7 +419,7 @@
                        &route);
        } else
                status = get_buffer_route(domain, buffer, &route);
-       
+
        TRACE("  route status: %s\n", strerror(status));
 
        if (status != B_OK)
@@ -422,8 +433,10 @@
 
 /*!    Tests if \a address is a local address in the domain.
 
-       \param _interface will be set to the interface belonging to that address
-               if non-NULL.
+       \param _interfaceAddress will be set to the interface address belonging 
to
+               that address if non-NULL. If the address \a _interfaceAddress 
points to
+               is not NULL, it is assumed that it already points to an 
address, which
+               is then released before the new address is assigned.
        \param _matchedType will be set to either zero or MSG_BCAST if non-NULL.
 */
 static bool
@@ -457,7 +470,7 @@
        TRACE("  it is, interface address %p\n", interfaceAddress);
 
        if (_interfaceAddress != NULL)
-               *_interfaceAddress = interfaceAddress;
+               set_interface_address(*_interfaceAddress, interfaceAddress);
        else
                interfaceAddress->ReleaseReference();
 
@@ -472,7 +485,10 @@
 
        \param unconfiguredOnly only unconfigured interfaces are taken into 
account.
        \param _interfaceAddress will be set to the first address of the 
interface
-               and domain belonging to that address if non-NULL.
+               and domain belonging to that address if non-NULL. If the address
+               \a _interfaceAddress points to is not NULL, it is assumed that 
it
+               already points to an address, which is then released before the 
new
+               address is assigned.
 */
 static bool
 datalink_is_local_link_address(net_domain* domain, bool unconfiguredOnly,
@@ -496,7 +512,7 @@
        }
 
        if (_interfaceAddress != NULL)
-               *_interfaceAddress = interfaceAddress;
+               set_interface_address(*_interfaceAddress, interfaceAddress);
        else
                interfaceAddress->ReleaseReference();
 

Modified: haiku/trunk/src/add-ons/kernel/network/stack/device_interfaces.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/network/stack/device_interfaces.cpp  
2010-08-15 13:17:52 UTC (rev 38117)
+++ haiku/trunk/src/add-ons/kernel/network/stack/device_interfaces.cpp  
2010-08-15 13:21:42 UTC (rev 38118)
@@ -59,7 +59,8 @@
                        if (atomic_get(&interface->monitor_count) > 0)
                                device_interface_monitor_receive(interface, 
buffer);
 
-                       buffer->interface_address = NULL;
+                       ASSERT(buffer->interface_address == NULL);
+
                        if (interface->deframe_func(interface->device, buffer) 
!= B_OK) {
                                gNetBufferModule.free(buffer);
                                continue;
@@ -307,7 +308,7 @@
        address.sdl_alen = interface->device->address.length;
        memcpy(LLADDR(&address), interface->device->address.data, 
address.sdl_alen);
 
-       address.sdl_len = sizeof(sockaddr_dl) - sizeof(address.sdl_data) 
+       address.sdl_len = sizeof(sockaddr_dl) - sizeof(address.sdl_data)
                + address.sdl_nlen + address.sdl_alen;
 }
 


Other related posts:

  • » [haiku-commits] r38118 - haiku/trunk/src/add-ons/kernel/network/stack - axeld