diff --git a/include/haproxy/frontend.h b/include/haproxy/frontend.h index eb986fb0b..8cd1a0a1c 100644 --- a/include/haproxy/frontend.h +++ b/include/haproxy/frontend.h @@ -26,6 +26,7 @@ int frontend_accept(struct stream *s); +int increment_actconn(); #endif /* _HAPROXY_FRONTEND_H */ diff --git a/src/frontend.c b/src/frontend.c index 105b24bcc..ad2e39ecb 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -165,6 +165,33 @@ int frontend_accept(struct stream *s) return -1; } +/* Increment current active connection counter. This ensures that global + * maxconn is not reached or exceeded. This must be done for every new frontend + * connection allocation. + * + * Returns the new actconn global value. If maxconn reached or exceeded, 0 is + * returned : the connection allocation should be cancelled. + */ +int increment_actconn() +{ + unsigned int count, next_actconn; + + do { + count = actconn; + if (unlikely(count >= global.maxconn)) { + /* maxconn reached */ + next_actconn = 0; + goto end; + } + + /* try to increment actconn */ + next_actconn = count + 1; + } while (!_HA_ATOMIC_CAS(&actconn, (int *)(&count), next_actconn) && __ha_cpu_relax()); + + end: + return next_actconn; +} + /************************************************************************/ /* All supported sample and ACL keywords must be declared here. */ /************************************************************************/ diff --git a/src/listener.c b/src/listener.c index 8a951f391..bbbf18036 100644 --- a/src/listener.c +++ b/src/listener.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -1114,18 +1115,14 @@ void listener_accept(struct listener *l) } if (!(l->bind_conf->options & BC_O_UNLIMITED)) { - do { - count = actconn; - if (unlikely(count >= global.maxconn)) { - /* the process was marked full or another - * thread is going to do it. - */ - next_actconn = 0; - expire = tick_add(now_ms, 1000); /* try again in 1 second */ - goto limit_global; - } - next_actconn = count + 1; - } while (!_HA_ATOMIC_CAS(&actconn, (int *)(&count), next_actconn)); + next_actconn = increment_actconn(); + if (!next_actconn) { + /* the process was marked full or another + * thread is going to do it. + */ + expire = tick_add(now_ms, 1000); /* try again in 1 second */ + goto limit_global; + } } /* be careful below, the listener might be shutting down in