diff options
| author | Robert Watson <rwatson@FreeBSD.org> | 2006-04-23 15:33:38 +0000 |
|---|---|---|
| committer | Robert Watson <rwatson@FreeBSD.org> | 2006-04-23 15:33:38 +0000 |
| commit | 6ca35d4b81734899fc0bf185e7a70471f1cb1d02 (patch) | |
| tree | 8a122b0130caf042e8510ea2c867d8e28c2b9b42 | |
| parent | 3f0c18fdda433b87a889335fa8472847973ade70 (diff) | |
Notes
| -rw-r--r-- | sys/kern/uipc_socket.c | 22 |
1 files changed, 5 insertions, 17 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index dadb06dcc630..e9eb4029c36b 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -397,6 +397,10 @@ solisten_proto(so, backlog) * - The protocol does not have an outstanding strong reference on the socket * (SS_PROTOREF). * + * - The socket is in a completed connection queue, so a process has been + * notified that it is present. If it is removed, the user process may + * block in accept() despite select() saying the socket was ready. + * * Otherwise, it will quietly abort so that a future call to sofree(), when * conditions are right, can succeed. */ @@ -410,7 +414,7 @@ sofree(so) SOCK_LOCK_ASSERT(so); if ((so->so_state & SS_NOFDREF) == 0 || so->so_count != 0 || - (so->so_state & SS_PROTOREF)) { + (so->so_state & SS_PROTOREF) || (so->so_qstate & SQ_COMP)) { SOCK_UNLOCK(so); ACCEPT_UNLOCK(); return; @@ -425,22 +429,6 @@ sofree(so) KASSERT((so->so_qstate & SQ_COMP) == 0 || (so->so_qstate & SQ_INCOMP) == 0, ("sofree: so->so_qstate is SQ_COMP and also SQ_INCOMP")); - /* - * accept(2) is responsible draining the completed - * connection queue and freeing those sockets, so - * we just return here if this socket is currently - * on the completed connection queue. Otherwise, - * accept(2) may hang after select(2) has indicating - * that a listening socket was ready. If it's an - * incomplete connection, we remove it from the queue - * and free it; otherwise, it won't be released until - * the listening socket is closed. - */ - if ((so->so_qstate & SQ_COMP) != 0) { - SOCK_UNLOCK(so); - ACCEPT_UNLOCK(); - return; - } TAILQ_REMOVE(&head->so_incomp, so, so_list); head->so_incqlen--; so->so_qstate &= ~SQ_INCOMP; |
