diff --git a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp index 0c4d9cae6a..5e69336787 100644 --- a/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp +++ b/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp @@ -1151,12 +1151,6 @@ TCPEndpoint::_EnterTimeWait() if (fState == TIME_WAIT) { _CancelConnectionTimers(); - - if (IsLocal()) { - // we do not use TIME_WAIT state for local connections - fFlags |= FLAG_DELETE_ON_CLOSE; - return; - } } _UpdateTimeWait(); @@ -1905,8 +1899,10 @@ TCPEndpoint::SegmentReceived(tcp_segment_header& segment, net_buffer* buffer) if ((fFlags & (FLAG_CLOSED | FLAG_DELETE_ON_CLOSE)) == (FLAG_CLOSED | FLAG_DELETE_ON_CLOSE)) { + locker.Unlock(); - gSocketModule->release_socket(socket); + if (gSocketModule->release_socket(socket)) + segmentAction |= DELETED_ENDPOINT; } return segmentAction; diff --git a/src/add-ons/kernel/network/protocols/tcp/tcp.cpp b/src/add-ons/kernel/network/protocols/tcp/tcp.cpp index 69e1d73971..e0dcbe2e83 100644 --- a/src/add-ons/kernel/network/protocols/tcp/tcp.cpp +++ b/src/add-ons/kernel/network/protocols/tcp/tcp.cpp @@ -11,6 +11,7 @@ #include "EndpointManager.h" #include "TCPEndpoint.h" +#include "tcp.h" #include #include @@ -710,7 +711,14 @@ tcp_receive_data(net_buffer* buffer) buffer->destination, buffer->source); if (endpoint != NULL) { segmentAction = endpoint->SegmentReceived(segment, buffer); - gSocketModule->release_socket(endpoint->socket); + + // There are some states in which the socket could have been deleted + // while handling a segment. If this flag is set in segmentAction + // then we know the socket has been freed and can skip releasing + // the reference acquired in EndpointManager::FindConnection() + // above. + if ((segmentAction & DELETED_ENDPOINT) == 0) + gSocketModule->release_socket(endpoint->socket); } else if ((segment.flags & TCP_FLAG_RESET) == 0) segmentAction = DROP | RESET; diff --git a/src/add-ons/kernel/network/protocols/tcp/tcp.h b/src/add-ons/kernel/network/protocols/tcp/tcp.h index 8ffccccc6d..f261f11da0 100644 --- a/src/add-ons/kernel/network/protocols/tcp/tcp.h +++ b/src/add-ons/kernel/network/protocols/tcp/tcp.h @@ -267,12 +267,12 @@ struct tcp_segment_header { }; enum tcp_segment_action { - KEEP = 0x00, - DROP = 0x01, - RESET = 0x02, - ACKNOWLEDGE = 0x04, - IMMEDIATE_ACKNOWLEDGE = 0x08, - DELETE_ENDPOINT = 0x10, + KEEP = 0x00, + DROP = 0x01, + RESET = 0x02, + ACKNOWLEDGE = 0x04, + IMMEDIATE_ACKNOWLEDGE = 0x08, + DELETED_ENDPOINT = 0x10, };