aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorRandall Stewart <rrs@FreeBSD.org>2010-06-06 19:24:32 +0000
committerRandall Stewart <rrs@FreeBSD.org>2010-06-06 19:24:32 +0000
commit0c7dc84076b64ef74c24f04400d572f75ef61bb4 (patch)
tree58e7f19bab4f9e4af9f486fa1a747f48b15f5ffa /sys/netinet
parent4f24f88ebb6d8128f9e241fa6d051a371484acfb (diff)
downloadsrc-0c7dc84076b64ef74c24f04400d572f75ef61bb4.tar.gz
src-0c7dc84076b64ef74c24f04400d572f75ef61bb4.zip
Ok, yet another bug in killing off all the hundreds
of apitesters.. Basically we end up with attempting to destroy a lock thats contended on. A cookie echo arrives at the same time that the close is happening. The close gets the lock but the cookie echo has already passed the check for the gone flag and is then locked waiting on the create lock.. when we go to destroy it bam. For now we do the timer destroy for all calls to close.. We can probably optimize this later so that we check whats being contended on and if there is contention then do the timer thing. but this is probably safest since the inp has been removed from all lists and references and only the timer can find it.. once the locks are released all other places will instantly see the GONE flag and bail (thats what the change in sctp_input is one place that was lacking the bail code). MFC after: 1 week
Notes
Notes: svn path=/head/; revision=208878
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/sctp_constants.h2
-rw-r--r--sys/netinet/sctp_input.c6
-rw-r--r--sys/netinet/sctp_pcb.c4
-rw-r--r--sys/netinet/sctputil.c2
4 files changed, 11 insertions, 3 deletions
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index 271e19702fbe..abf58268d24d 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -894,7 +894,7 @@ __FBSDID("$FreeBSD$");
/* third argument */
#define SCTP_CALLED_DIRECTLY_NOCMPSET 0
#define SCTP_CALLED_AFTER_CMPSET_OFCLOSE 1
-
+#define SCTP_CALLED_FROM_INPKILL_TIMER 2
/* second argument */
#define SCTP_FREE_SHOULD_USE_ABORT 1
#define SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE 0
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 95114cc4d64c..8b2a9d598dbe 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -4862,6 +4862,7 @@ process_control_chunks:
} else {
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
/* We are not interested anymore */
+ abend:
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
@@ -4912,6 +4913,11 @@ process_control_chunks:
if (linp) {
SCTP_ASOC_CREATE_LOCK(linp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
+ SCTP_ASOC_CREATE_UNLOCK(linp);
+ goto abend;
+ }
}
if (netp) {
ret_buf =
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 0ef5383a6a02..f9e029a1e0c5 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -3423,7 +3423,9 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
#endif
return;
}
- if ((inp->refcount) || (inp->sctp_flags & SCTP_PCB_FLAGS_CLOSE_IP)) {
+ if ((inp->refcount) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_CLOSE_IP) ||
+ (from != SCTP_CALLED_FROM_INPKILL_TIMER)) {
(void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer);
sctp_timer_start(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL);
SCTP_INP_WUNLOCK(inp);
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index a6fb7b37ebdf..dea903603a2a 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -1898,7 +1898,7 @@ sctp_timeout_handler(void *t)
SCTP_INP_DECR_REF(inp);
sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_3);
sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
- SCTP_CALLED_DIRECTLY_NOCMPSET);
+ SCTP_CALLED_FROM_INPKILL_TIMER);
inp = NULL;
goto out_no_decr;
default: