* Close a socket on last file table reference removal. Initiate disconnect * if connected. Free socket when disconnect complete. * * This function will sorele() the socket. Note that soclose() may be called * prior to the ref count reaching zero. The actual socket structure will * not be freed until the ref count reaches zero. */
| 1175 | * not be freed until the ref count reaches zero. |
| 1176 | */ |
| 1177 | int |
| 1178 | soclose(struct socket *so) |
| 1179 | { |
| 1180 | struct accept_queue lqueue; |
| 1181 | bool listening; |
| 1182 | int error = 0; |
| 1183 | |
| 1184 | KASSERT(!(so->so_state & SS_NOFDREF), ("soclose: SS_NOFDREF on enter")); |
| 1185 | |
| 1186 | CURVNET_SET(so->so_vnet); |
| 1187 | funsetown(&so->so_sigio); |
| 1188 | if (so->so_state & SS_ISCONNECTED) { |
| 1189 | if ((so->so_state & SS_ISDISCONNECTING) == 0) { |
| 1190 | error = sodisconnect(so); |
| 1191 | if (error) { |
| 1192 | if (error == ENOTCONN) |
| 1193 | error = 0; |
| 1194 | goto drop; |
| 1195 | } |
| 1196 | } |
| 1197 | |
| 1198 | if ((so->so_options & SO_LINGER) != 0 && so->so_linger != 0) { |
| 1199 | if ((so->so_state & SS_ISDISCONNECTING) && |
| 1200 | (so->so_state & SS_NBIO)) |
| 1201 | goto drop; |
| 1202 | while (so->so_state & SS_ISCONNECTED) { |
| 1203 | error = tsleep(&so->so_timeo, |
| 1204 | PSOCK | PCATCH, "soclos", |
| 1205 | so->so_linger * hz); |
| 1206 | if (error) |
| 1207 | break; |
| 1208 | } |
| 1209 | } |
| 1210 | } |
| 1211 | |
| 1212 | drop: |
| 1213 | if (so->so_proto->pr_usrreqs->pru_close != NULL) |
| 1214 | (*so->so_proto->pr_usrreqs->pru_close)(so); |
| 1215 | |
| 1216 | SOCK_LOCK(so); |
| 1217 | if ((listening = (so->so_options & SO_ACCEPTCONN))) { |
| 1218 | struct socket *sp; |
| 1219 | |
| 1220 | TAILQ_INIT(&lqueue); |
| 1221 | TAILQ_SWAP(&lqueue, &so->sol_incomp, socket, so_list); |
| 1222 | TAILQ_CONCAT(&lqueue, &so->sol_comp, so_list); |
| 1223 | |
| 1224 | so->sol_qlen = so->sol_incqlen = 0; |
| 1225 | |
| 1226 | TAILQ_FOREACH(sp, &lqueue, so_list) { |
| 1227 | SOCK_LOCK(sp); |
| 1228 | sp->so_qstate = SQ_NONE; |
| 1229 | sp->so_listen = NULL; |
| 1230 | SOCK_UNLOCK(sp); |
| 1231 | /* Guaranteed not to be the last. */ |
| 1232 | refcount_release(&so->so_count); |
| 1233 | } |
| 1234 | } |
no test coverage detected