This introduces a regression reported by koobs@ when running a pyhton test suite on a loaded system. This patch resulted in a failing accept() call, when the association was setup and gracefully shutdown by the peer before accept was called. So the following packetdrill script would fail: +0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3 +0.0 bind(3, ..., ...) = 0 +0.0 listen(3, 1) = 0 +0.0 < sctp: INIT[flgs=0, tag=1, a_rwnd=15000, os=1, is=1, tsn=1] +0.0 > sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=..., os=..., is=..., tsn=1, ...] +0.1 < sctp: COOKIE_ECHO[flgs=0, len=..., val=...] +0.0 > sctp: COOKIE_ACK[flgs=0] +0.0 < sctp: DATA[flgs=BE, len=116, tsn=1, sid=0, ssn=0, ppid=0] +0.0 > sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=..., gaps=[], dups=[]] +0.0 < sctp: SHUTDOWN[flgs=0, cum_tsn=0] +0.0 > sctp: SHUTDOWN_ACK[flgs=0] +0.0 < sctp: SHUTDOWN_COMPLETE[flgs=0] +0.0 accept(3, ..., ...) = 4 +0.0 close(3) = 0 +0.0 recv(4, ..., 4096, 0) = 100 +0.0 recv(4, ..., 4096, 0) = 0 +0.0 close(4) = 0 Reported by: koops@
This commit is contained in:
parent
23e3c0880d
commit
24187cfe72
@ -4739,31 +4739,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
|||||||
else
|
else
|
||||||
so = inp->sctp_socket;
|
so = inp->sctp_socket;
|
||||||
|
|
||||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
|
|
||||||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
|
|
||||||
/*
|
|
||||||
* For TCP type we need special handling when we are
|
|
||||||
* connected. We also include the peel'ed off ones to.
|
|
||||||
*/
|
|
||||||
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
|
|
||||||
inp->sctp_flags &= ~SCTP_PCB_FLAGS_CONNECTED;
|
|
||||||
inp->sctp_flags |= SCTP_PCB_FLAGS_WAS_CONNECTED;
|
|
||||||
if (so) {
|
|
||||||
SOCKBUF_LOCK(&so->so_rcv);
|
|
||||||
so->so_state &= ~(SS_ISCONNECTING |
|
|
||||||
SS_ISDISCONNECTING |
|
|
||||||
SS_ISCONFIRMING |
|
|
||||||
SS_ISCONNECTED);
|
|
||||||
so->so_state |= SS_ISDISCONNECTED;
|
|
||||||
socantrcvmore_locked(so);
|
|
||||||
socantsendmore(so);
|
|
||||||
sctp_sowwakeup(inp, so);
|
|
||||||
sctp_sorwakeup(inp, so);
|
|
||||||
SCTP_SOWAKEUP(so);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We used timer based freeing if a reader or writer is in the way.
|
* We used timer based freeing if a reader or writer is in the way.
|
||||||
* So we first check if we are actually being called from a timer,
|
* So we first check if we are actually being called from a timer,
|
||||||
@ -4891,6 +4866,31 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
|||||||
/* nothing around */
|
/* nothing around */
|
||||||
so = NULL;
|
so = NULL;
|
||||||
|
|
||||||
|
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
|
||||||
|
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
|
||||||
|
/*
|
||||||
|
* For TCP type we need special handling when we are
|
||||||
|
* connected. We also include the peel'ed off ones to.
|
||||||
|
*/
|
||||||
|
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
|
||||||
|
inp->sctp_flags &= ~SCTP_PCB_FLAGS_CONNECTED;
|
||||||
|
inp->sctp_flags |= SCTP_PCB_FLAGS_WAS_CONNECTED;
|
||||||
|
if (so) {
|
||||||
|
SOCKBUF_LOCK(&so->so_rcv);
|
||||||
|
so->so_state &= ~(SS_ISCONNECTING |
|
||||||
|
SS_ISDISCONNECTING |
|
||||||
|
SS_ISCONFIRMING |
|
||||||
|
SS_ISCONNECTED);
|
||||||
|
so->so_state |= SS_ISDISCONNECTED;
|
||||||
|
socantrcvmore_locked(so);
|
||||||
|
socantsendmore(so);
|
||||||
|
sctp_sowwakeup(inp, so);
|
||||||
|
sctp_sorwakeup(inp, so);
|
||||||
|
SCTP_SOWAKEUP(so);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make it invalid too, that way if its about to run it will abort
|
* Make it invalid too, that way if its about to run it will abort
|
||||||
* and return.
|
* and return.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user