|
@@ -1384,6 +1384,7 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
|
|
|
struct sctp_endpoint *ep;
|
|
|
struct sctp_association *asoc;
|
|
|
struct list_head *pos, *temp;
|
|
|
+ unsigned int data_was_unread;
|
|
|
|
|
|
SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout);
|
|
|
|
|
@@ -1393,6 +1394,10 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
|
|
|
|
|
|
ep = sctp_sk(sk)->ep;
|
|
|
|
|
|
+ /* Clean up any skbs sitting on the receive queue. */
|
|
|
+ data_was_unread = sctp_queue_purge_ulpevents(&sk->sk_receive_queue);
|
|
|
+ data_was_unread += sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby);
|
|
|
+
|
|
|
/* Walk all associations on an endpoint. */
|
|
|
list_for_each_safe(pos, temp, &ep->asocs) {
|
|
|
asoc = list_entry(pos, struct sctp_association, asocs);
|
|
@@ -1410,7 +1415,9 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
|
|
|
+ if (data_was_unread || !skb_queue_empty(&asoc->ulpq.lobby) ||
|
|
|
+ !skb_queue_empty(&asoc->ulpq.reasm) ||
|
|
|
+ (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime)) {
|
|
|
struct sctp_chunk *chunk;
|
|
|
|
|
|
chunk = sctp_make_abort_user(asoc, NULL, 0);
|
|
@@ -1420,10 +1427,6 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
|
|
|
sctp_primitive_SHUTDOWN(asoc, NULL);
|
|
|
}
|
|
|
|
|
|
- /* Clean up any skbs sitting on the receive queue. */
|
|
|
- sctp_queue_purge_ulpevents(&sk->sk_receive_queue);
|
|
|
- sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby);
|
|
|
-
|
|
|
/* On a TCP-style socket, block for at most linger_time if set. */
|
|
|
if (sctp_style(sk, TCP) && timeout)
|
|
|
sctp_wait_for_close(sk, timeout);
|