[BUG] stream_sock: disable listener when system resources are exhausted

When an accept() returns -1 ENFILE du to system limits, it leaves the
connection pending in the backlog and epoll() comes back immediately
afterwards trying to make it accept it again. This causes haproxy to
remain at 100% CPU until something makes an accept() possible again.
Now upon such resource shortage, we mark the listener FULL so that we
only enable it again once at least one connection has been released.
In fact we only do that if there are some active connections on this
proxy, so that it has a chance to be marked not full again. This makes
haproxy remain idle when all resources are used, which helps a lot
releasing those resource as fast as possible.

Backport to 1.4 might be desirable but difficult and tricky.
This commit is contained in:
Willy Tarreau 2011-07-22 16:56:33 +02:00
parent 4827fd2a7e
commit 100298749b

View File

@ -1221,12 +1221,20 @@ int stream_sock_accept(int fd)
send_log(p, LOG_EMERG, send_log(p, LOG_EMERG,
"Proxy %s reached system FD limit at %d. Please check system tunables.\n", "Proxy %s reached system FD limit at %d. Please check system tunables.\n",
p->id, maxfd); p->id, maxfd);
if (l->nbconn) {
EV_FD_CLR(l->fd, DIR_RD);
l->state = LI_FULL;
}
return 0; return 0;
case EMFILE: case EMFILE:
if (p) if (p)
send_log(p, LOG_EMERG, send_log(p, LOG_EMERG,
"Proxy %s reached process FD limit at %d. Please check 'ulimit-n' and restart.\n", "Proxy %s reached process FD limit at %d. Please check 'ulimit-n' and restart.\n",
p->id, maxfd); p->id, maxfd);
if (l->nbconn) {
EV_FD_CLR(l->fd, DIR_RD);
l->state = LI_FULL;
}
return 0; return 0;
case ENOBUFS: case ENOBUFS:
case ENOMEM: case ENOMEM:
@ -1234,6 +1242,10 @@ int stream_sock_accept(int fd)
send_log(p, LOG_EMERG, send_log(p, LOG_EMERG,
"Proxy %s reached system memory limit at %d sockets. Please check system tunables.\n", "Proxy %s reached system memory limit at %d sockets. Please check system tunables.\n",
p->id, maxfd); p->id, maxfd);
if (l->nbconn) {
EV_FD_CLR(l->fd, DIR_RD);
l->state = LI_FULL;
}
return 0; return 0;
default: default:
return 0; return 0;