BUG/MINOR: stick_table: Prevent conn_cur from underflowing

When using the peers feature a race condition could prevent
a connection from being properly counted. When this connection
exits it is being "uncounted" nonetheless, leading to a possible
underflow (-1) of the conn_curr stick table entry in the following
scenario :

  - Connect to peer A     (A=1, B=0)
  - Peer A sends 1 to B   (A=1, B=1)
  - Kill connection to A  (A=0, B=1)
  - Connect to peer B     (A=0, B=2)
  - Peer A sends 0 to B   (A=0, B=0)
  - Peer B sends 0/2 to A (A=?, B=0)
  - Kill connection to B  (A=?, B=-1)
  - Peer B sends -1 to A  (A=-1, B=-1)

This fix may be backported to all supported branches.
This commit is contained in:
Tim Duesterhus 2019-01-04 00:11:59 +01:00 committed by Willy Tarreau
parent f8f8ddf3af
commit 8b87c01c4d
2 changed files with 6 additions and 3 deletions

View File

@ -62,7 +62,8 @@ static inline void session_store_counters(struct session *sess)
if (ptr) {
HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock);
stktable_data_cast(ptr, conn_cur)--;
if (stktable_data_cast(ptr, conn_cur) > 0)
stktable_data_cast(ptr, conn_cur)--;
HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);

View File

@ -103,7 +103,8 @@ static inline void stream_store_counters(struct stream *s)
if (ptr) {
HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock);
stktable_data_cast(ptr, conn_cur)--;
if (stktable_data_cast(ptr, conn_cur) > 0)
stktable_data_cast(ptr, conn_cur)--;
HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
@ -141,7 +142,8 @@ static inline void stream_stop_content_counters(struct stream *s)
if (ptr) {
HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock);
stktable_data_cast(ptr, conn_cur)--;
if (stktable_data_cast(ptr, conn_cur) > 0)
stktable_data_cast(ptr, conn_cur)--;
HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);