diff --git a/headers/private/net/net_socket.h b/headers/private/net/net_socket.h index 12fe06b7a8..527d8ad27d 100644 --- a/headers/private/net/net_socket.h +++ b/headers/private/net/net_socket.h @@ -71,7 +71,7 @@ struct net_socket_module_info { struct net_stat *stat); // connections - void (*acquire_socket)(net_socket *socket); + bool (*acquire_socket)(net_socket *socket); bool (*release_socket)(net_socket *socket); status_t (*spawn_pending_socket)(net_socket *parent, diff --git a/src/add-ons/kernel/network/protocols/tcp/EndpointManager.cpp b/src/add-ons/kernel/network/protocols/tcp/EndpointManager.cpp index 27613ad03e..8420e334fe 100644 --- a/src/add-ons/kernel/network/protocols/tcp/EndpointManager.cpp +++ b/src/add-ons/kernel/network/protocols/tcp/EndpointManager.cpp @@ -320,8 +320,8 @@ EndpointManager::FindConnection(sockaddr* local, sockaddr* peer) if (endpoint != NULL) { TRACE(("TCP: Received packet corresponds to explicit endpoint %p\n", endpoint)); - gSocketModule->acquire_socket(endpoint->socket); - return endpoint; + if (gSocketModule->acquire_socket(endpoint->socket)) + return endpoint; } // no explicit endpoint exists, check for wildcard endpoints @@ -333,8 +333,8 @@ EndpointManager::FindConnection(sockaddr* local, sockaddr* peer) if (endpoint != NULL) { TRACE(("TCP: Received packet corresponds to wildcard endpoint %p\n", endpoint)); - gSocketModule->acquire_socket(endpoint->socket); - return endpoint; + if (gSocketModule->acquire_socket(endpoint->socket)) + return endpoint; } SocketAddressStorage localWildcard(AddressModule()); @@ -345,8 +345,8 @@ EndpointManager::FindConnection(sockaddr* local, sockaddr* peer) if (endpoint != NULL) { TRACE(("TCP: Received packet corresponds to local wildcard endpoint " "%p\n", endpoint)); - gSocketModule->acquire_socket(endpoint->socket); - return endpoint; + if (gSocketModule->acquire_socket(endpoint->socket)) + return endpoint; } // no matching endpoint exists diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp index 49a8c6462f..b79886708b 100644 --- a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp +++ b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp @@ -673,7 +673,7 @@ TCPEndpoint::Accept(struct net_socket** _acceptedSocket) status = acquire_sem_etc(fAcceptSemaphore, 1, B_ABSOLUTE_TIMEOUT | B_CAN_INTERRUPT, timeout); - if (status < B_OK) + if (status != B_OK) return status; locker.Lock(); @@ -682,7 +682,7 @@ TCPEndpoint::Accept(struct net_socket** _acceptedSocket) if (status == B_OK) TRACE(" Accept() returning %p", (*_acceptedSocket)->first_protocol); #endif - } while (status < B_OK); + } while (status != B_OK); return status; } diff --git a/src/add-ons/kernel/network/stack/net_socket.cpp b/src/add-ons/kernel/network/stack/net_socket.cpp index e9ddd3b197..786f4c534a 100644 --- a/src/add-ons/kernel/network/stack/net_socket.cpp +++ b/src/add-ons/kernel/network/stack/net_socket.cpp @@ -598,11 +598,20 @@ socket_get_next_stat(uint32* _cookie, int family, struct net_stat* stat) // #pragma mark - connections -void +bool socket_acquire(net_socket* _socket) { net_socket_private* socket = (net_socket_private*)_socket; + + // During destruction, the socket might still be accessible over its endpoint + // protocol. We need to make sure the endpoint cannot acquire the socket + // anymore -- while not obvious, the endpoint protocol is responsible for the + // proper locking here. + if (socket->CountReferences() == 0) + return false; + socket->AddReference(); + return true; }