i'm not sure this is a perfect solution. i just don't have enough of the plan 9 ip stack loaded into cache to be sure nothing's been forgotten. but give this patch a whirl. basically, i think the problem is that inittcpctl() was stepping on timers that might have been active. these timers need to be shutdown. unfortunately, tcpclose() and localclose() are too agressive. cleanupconnection() is a chopped-down version of localclose. - erik /n/sources/plan9//sys/src/9/ip/tcp.c:782,787 - tcp.c:782,813 return mtu; } + static void + cleanupconnection(Conv *s) + { + Tcpctl *tcb; + Reseq *rp,*rp1; + Tcppriv *tpriv; + + tpriv = s->p->priv; + tcb = (Tcpctl*)s->ptcl; + + iphtrem(&tpriv->ht, s); + + tcphalt(tpriv, &tcb->timer); + tcphalt(tpriv, &tcb->rtt_timer); + tcphalt(tpriv, &tcb->acktimer); + tcphalt(tpriv, &tcb->katimer); + + /* Flush reassembly queue; nothing more can arrive */ + for(rp = tcb->reseq; rp != nil; rp = rp1) { + rp1 = rp->next; + freeblist(rp->bp); + free(rp); + } + tcb->reseq = nil; + } + void inittcpctl(Conv *s, int mode) { /n/sources/plan9//sys/src/9/ip/tcp.c:792,798 - tcp.c:818,827 tcb = (Tcpctl*)s->ptcl; - memset(tcb, 0, sizeof(Tcpctl)); + if(tcb->timer.arg) // c->state != Idle? + cleanupconnection(s); + else + memset(tcb, 0, sizeof(Tcpctl)); tcb->ssthresh = 65535; tcb->srtt = tcp_irtt<