[MEDIUM] stream_sock: don't close prematurely when nolinger is set

When the nolinger option is used, we must not close too fast because
some data might be left unsent. Instead we must proceed with a normal
shutdown first, then a close. Also, we want to avoid merging FIN with
the last segment if nolinger is set, because if that one gets lost,
there is no chance for it to be retransmitted.
This commit is contained in:
Willy Tarreau 2009-06-28 11:09:07 +02:00
parent 5d01a63b78
commit 5d707e1aaa
4 changed files with 14 additions and 1 deletions

View File

@ -65,6 +65,7 @@ enum {
#define FD_FL_TCP 0x0001 /* socket is TCP */
#define FD_FL_TCP_NODELAY 0x0002
#define FD_FL_TCP_CORK 0x0004
#define FD_FL_TCP_NOLING 0x0008 /* lingering disabled */
/* info about one given fd */
struct fdtab {

View File

@ -418,6 +418,9 @@ int event_accept(int fd) {
fdtab[cfd].owner = &s->si[0];
fdtab[cfd].state = FD_STREADY;
fdtab[cfd].flags = FD_FL_TCP | FD_FL_TCP_NODELAY;
if (p->options & PR_O_TCP_NOLING)
fdtab[cfd].flags |= FD_FL_TCP_NOLING;
fdtab[cfd].cb[DIR_RD].f = l->proto->read;
fdtab[cfd].cb[DIR_RD].b = s->req;
fdtab[cfd].cb[DIR_WR].f = l->proto->write;

View File

@ -289,6 +289,9 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
fdtab[fd].owner = listener; /* reference the listener instead of a task */
fdtab[fd].state = FD_STLISTEN;
fdtab[fd].flags = FD_FL_TCP;
if (listener->options & LI_O_NOLINGER)
fdtab[fd].flags |= FD_FL_TCP_NOLING;
fdtab[fd].peeraddr = NULL;
fdtab[fd].peerlen = 0;
tcp_return:

View File

@ -579,7 +579,7 @@ static int stream_sock_write_loop(struct stream_interface *si, struct buffer *b)
* buffer but we know we will close, so we try to merge the ongoing FIN
* with the last data segment.
*/
if ((fdtab[si->fd].flags & (FD_FL_TCP|FD_FL_TCP_CORK)) == FD_FL_TCP) {
if ((fdtab[si->fd].flags & (FD_FL_TCP|FD_FL_TCP_NOLING|FD_FL_TCP_CORK)) == FD_FL_TCP) {
if (unlikely((b->send_max == b->l &&
(b->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR)) ==
(BF_WRITE_ENA|BF_SHUTR)))) {
@ -829,6 +829,12 @@ void stream_sock_shutw(struct stream_interface *si)
shutdown(si->fd, SHUT_WR);
return;
}
if (fdtab[si->fd].flags & FD_FL_TCP_NOLING) {
/* we have to shut before closing if we disable lingering */
EV_FD_CLR(si->fd, DIR_WR);
shutdown(si->fd, SHUT_WR);
}
/* fall through */
case SI_ST_CON:
/* we may have to close a pending connection, and mark the