Skip to content

Commit

Permalink
BUG/MEDIUM: listener: Acquire proxy's lock in relax_listener() if nec…
Browse files Browse the repository at this point in the history
…essary

Listener functions must follow a common locking pattern:

  1. Get the proxy's lock if necessary
  2. Get the protocol's lock if necessary
  3. Get the listener's lock if necessary

We must take care to respect this order to avoid any ABBA issue. However, an
issue was introduced in the commit bcad7e6 ("MINOR: listener: add
relax_listener() function"). relax_listener() gets the lisener's lock and if
resume_listener() is called, the proxy's lock is then acquired.

So to fix the issue, the proxy's lock is first acquired in relax_listener(),
if necessary.

This patch should fix the issue #2222. It must be backported as far as 2.4
because the above commit is marked to be backported there.
  • Loading branch information
capflam committed Jul 21, 2023
1 parent 462b54d commit ff1c803
Showing 1 changed file with 9 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/listener.c
Original file line number Diff line number Diff line change
Expand Up @@ -633,18 +633,26 @@ int resume_listener(struct listener *l, int lpx, int lli)
*/
int relax_listener(struct listener *l, int lpx, int lli)
{
struct proxy *px = l->bind_conf->frontend;
int ret = 1;

if (!lpx && px)
HA_RWLOCK_WRLOCK(PROXY_LOCK, &px->lock);

if (!lli)
HA_RWLOCK_WRLOCK(LISTENER_LOCK, &l->lock);

if (l->state != LI_FULL && l->state != LI_LIMITED)
goto end; /* listener may be suspended or even stopped */
ret = resume_listener(l, lpx, 1);
ret = resume_listener(l, 1, 1);

end:
if (!lli)
HA_RWLOCK_WRUNLOCK(LISTENER_LOCK, &l->lock);

if (!lpx && px)
HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock);

return ret;
}

Expand Down

0 comments on commit ff1c803

Please sign in to comment.