From: Willy Tarreau Date: Sat, 5 Jun 2010 08:49:41 +0000 (+0200) Subject: [MEDIUM] frontend: count the incoming connection earlier X-Git-Tag: v1.5-dev8~573 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=24dcaf3450a7de4cb39b9c27dcaceacc0346a4bc;p=thirdparty%2Fhaproxy.git [MEDIUM] frontend: count the incoming connection earlier The frontend's connection was accounted for once the session was instanciated. This was problematic because the early ACLs weren't able to correctly account for the number of concurrent connections. Now we count the connection once it is assigned to the frontend. It also brings the nice advantage of being more symmetrical, because the stream_sock's accept() does not have to account for that anymore, only the session's accept() does. --- diff --git a/src/session.c b/src/session.c index dcb3fdcdb6..ba8cec132e 100644 --- a/src/session.c +++ b/src/session.c @@ -94,6 +94,8 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) s->logs.accept_date = date; /* user-visible date for logging */ s->logs.tv_accept = now; /* corrected date for internal use */ s->uniq_id = totalconn; + p->feconn++; /* beconn will be increased once assigned */ + proxy_inc_fe_conn_ctr(l, p); /* note: cum_beconn will be increased once assigned */ t->process = l->handler; @@ -121,10 +123,13 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) pool_free2(pool2_session, s); /* let's do a no-linger now to close with a single RST. */ setsockopt(cfd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger)); + p->feconn--; return 0; } /* This session was accepted, count it now */ + if (p->feconn > p->counters.feconn_max) + p->counters.feconn_max = p->feconn; proxy_inc_fe_sess_ctr(l, p); /* this part should be common with other protocols */ @@ -253,6 +258,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) task_free(t); LIST_DEL(&s->list); pool_free2(pool2_session, s); + p->feconn--; return 0; } } @@ -270,6 +276,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) out_free_req: pool_free2(pool2_buffer, s->req); out_free_task: + p->feconn--; task_free(t); out_free_session: LIST_DEL(&s->list); diff --git a/src/stream_sock.c b/src/stream_sock.c index 93e3daf591..2d5ef6d704 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -1184,6 +1184,15 @@ int stream_sock_accept(int fd) goto out_close; } + actconn++; + totalconn++; + l->nbconn++; + + if (l->counters) { + if (l->nbconn > l->counters->conn_max) + l->counters->conn_max = l->nbconn; + } + ret = l->accept(l, cfd, &addr); if (unlikely(ret < 0)) { /* critical error encountered, generally a resource shortage */ @@ -1191,32 +1200,22 @@ int stream_sock_accept(int fd) EV_FD_CLR(fd, DIR_RD); p->state = PR_STIDLE; } + actconn--; + l->nbconn--; goto out_close; } else if (unlikely(ret == 0)) { /* ignore this connection */ + actconn--; + l->nbconn--; close(cfd); continue; } - actconn++; - totalconn++; - l->nbconn++; /* warning! right now, it's up to the handler to decrease this */ if (l->nbconn >= l->maxconn) { EV_FD_CLR(l->fd, DIR_RD); l->state = LI_FULL; } - - if (p) { - p->feconn++; /* beconn will be increased later */ - if (p->feconn > p->counters.feconn_max) - p->counters.feconn_max = p->feconn; - } - - if (l->counters) { - if (l->nbconn > l->counters->conn_max) - l->counters->conn_max = l->nbconn; - } } /* end of while (p->feconn < p->maxconn) */ return 0;