* Evaluate the reference count and named references on a socket; if no * references remain, free it. This should be called whenever a reference is * released, such as in sorele(), but also when named reference flags are * cleared in socket or protocol code. * * sofree() will free the socket if: * * - There are no outstanding file descriptor references or related consumers * (so_count ==
| 1072 | * block in accept() despite select() saying the socket was ready. |
| 1073 | */ |
| 1074 | void |
| 1075 | sofree(struct socket *so) |
| 1076 | { |
| 1077 | struct protosw *pr = so->so_proto; |
| 1078 | |
| 1079 | SOCK_LOCK_ASSERT(so); |
| 1080 | |
| 1081 | if ((so->so_state & SS_NOFDREF) == 0 || so->so_count != 0 || |
| 1082 | (so->so_state & SS_PROTOREF) || (so->so_qstate == SQ_COMP)) { |
| 1083 | SOCK_UNLOCK(so); |
| 1084 | return; |
| 1085 | } |
| 1086 | |
| 1087 | if (!SOLISTENING(so) && so->so_qstate == SQ_INCOMP) { |
| 1088 | struct socket *sol; |
| 1089 | |
| 1090 | sol = so->so_listen; |
| 1091 | KASSERT(sol, ("%s: so %p on incomp of NULL", __func__, so)); |
| 1092 | |
| 1093 | /* |
| 1094 | * To solve race between close of a listening socket and |
| 1095 | * a socket on its incomplete queue, we need to lock both. |
| 1096 | * The order is first listening socket, then regular. |
| 1097 | * Since we don't have SS_NOFDREF neither SS_PROTOREF, this |
| 1098 | * function and the listening socket are the only pointers |
| 1099 | * to so. To preserve so and sol, we reference both and then |
| 1100 | * relock. |
| 1101 | * After relock the socket may not move to so_comp since it |
| 1102 | * doesn't have PCB already, but it may be removed from |
| 1103 | * so_incomp. If that happens, we share responsiblity on |
| 1104 | * freeing the socket, but soclose() has already removed |
| 1105 | * it from queue. |
| 1106 | */ |
| 1107 | soref(sol); |
| 1108 | soref(so); |
| 1109 | SOCK_UNLOCK(so); |
| 1110 | SOLISTEN_LOCK(sol); |
| 1111 | SOCK_LOCK(so); |
| 1112 | if (so->so_qstate == SQ_INCOMP) { |
| 1113 | KASSERT(so->so_listen == sol, |
| 1114 | ("%s: so %p migrated out of sol %p", |
| 1115 | __func__, so, sol)); |
| 1116 | TAILQ_REMOVE(&sol->sol_incomp, so, so_list); |
| 1117 | sol->sol_incqlen--; |
| 1118 | /* This is guarenteed not to be the last. */ |
| 1119 | refcount_release(&sol->so_count); |
| 1120 | so->so_qstate = SQ_NONE; |
| 1121 | so->so_listen = NULL; |
| 1122 | } else |
| 1123 | KASSERT(so->so_listen == NULL, |
| 1124 | ("%s: so %p not on (in)comp with so_listen", |
| 1125 | __func__, so)); |
| 1126 | sorele(sol); |
| 1127 | KASSERT(so->so_count == 1, |
| 1128 | ("%s: so %p count %u", __func__, so, so->so_count)); |
| 1129 | so->so_count = 0; |
| 1130 | } |
| 1131 | if (SOLISTENING(so)) |
no test coverage detected