mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-05-10 11:48:01 +00:00
BUG/MEDIUM: cli: Deadlock when setting frontend maxconn
The proxy lock state isn't passed down to relax_listener
through dequeue_proxy_listeners, which causes a deadlock
in relax_listener when it tries to get that lock.
Backporting: Older versions didn't have relax_listener and directly called
resume_listener in dequeue_proxy_listeners. lpx should just be passed directly
to resume_listener then.
The bug was introduced in commit 001328873c
[cf: This patch should fix the issue #2726. It must be backported as far as
2.4]
This commit is contained in:
parent
96edacc546
commit
a889413f5e
@ -94,7 +94,7 @@ void enable_listener(struct listener *listener);
|
|||||||
void dequeue_all_listeners(void);
|
void dequeue_all_listeners(void);
|
||||||
|
|
||||||
/* Dequeues all listeners waiting for a resource in proxy <px>'s queue */
|
/* Dequeues all listeners waiting for a resource in proxy <px>'s queue */
|
||||||
void dequeue_proxy_listeners(struct proxy *px);
|
void dequeue_proxy_listeners(struct proxy *px, int lpx);
|
||||||
|
|
||||||
/* This function closes the listening socket for the specified listener,
|
/* This function closes the listening socket for the specified listener,
|
||||||
* provided that it's already in a listening state. The listener enters the
|
* provided that it's already in a listening state. The listener enters the
|
||||||
|
@ -707,8 +707,12 @@ void dequeue_all_listeners()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dequeues all listeners waiting for a resource in proxy <px>'s queue */
|
/* Dequeues all listeners waiting for a resource in proxy <px>'s queue
|
||||||
void dequeue_proxy_listeners(struct proxy *px)
|
* The caller is responsible for indicating in lpx, whether the proxy's lock
|
||||||
|
* is already held (non-zero) or not (zero) so that this information can be
|
||||||
|
* passed to relax_listener
|
||||||
|
*/
|
||||||
|
void dequeue_proxy_listeners(struct proxy *px, int lpx)
|
||||||
{
|
{
|
||||||
struct listener *listener;
|
struct listener *listener;
|
||||||
|
|
||||||
@ -716,7 +720,7 @@ void dequeue_proxy_listeners(struct proxy *px)
|
|||||||
/* This cannot fail because the listeners are by definition in
|
/* This cannot fail because the listeners are by definition in
|
||||||
* the LI_LIMITED state.
|
* the LI_LIMITED state.
|
||||||
*/
|
*/
|
||||||
relax_listener(listener, 0, 0);
|
relax_listener(listener, lpx, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1558,7 +1562,7 @@ void listener_accept(struct listener *l)
|
|||||||
|
|
||||||
if (p && !MT_LIST_ISEMPTY(&p->listener_queue) &&
|
if (p && !MT_LIST_ISEMPTY(&p->listener_queue) &&
|
||||||
(!p->fe_sps_lim || freq_ctr_remain(&p->fe_counters.sess_per_sec, p->fe_sps_lim, 0) > 0))
|
(!p->fe_sps_lim || freq_ctr_remain(&p->fe_counters.sess_per_sec, p->fe_sps_lim, 0) > 0))
|
||||||
dequeue_proxy_listeners(p);
|
dequeue_proxy_listeners(p, 0);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1617,7 +1621,7 @@ void listener_release(struct listener *l)
|
|||||||
|
|
||||||
if (fe && !MT_LIST_ISEMPTY(&fe->listener_queue) &&
|
if (fe && !MT_LIST_ISEMPTY(&fe->listener_queue) &&
|
||||||
(!fe->fe_sps_lim || freq_ctr_remain(&fe->fe_counters.sess_per_sec, fe->fe_sps_lim, 0) > 0))
|
(!fe->fe_sps_lim || freq_ctr_remain(&fe->fe_counters.sess_per_sec, fe->fe_sps_lim, 0) > 0))
|
||||||
dequeue_proxy_listeners(fe);
|
dequeue_proxy_listeners(fe, 0);
|
||||||
else {
|
else {
|
||||||
unsigned int wait;
|
unsigned int wait;
|
||||||
int expire = TICK_ETERNITY;
|
int expire = TICK_ETERNITY;
|
||||||
|
@ -2030,7 +2030,7 @@ struct task *manage_proxy(struct task *t, void *context, unsigned int state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The proxy is not limited so we can re-enable any waiting listener */
|
/* The proxy is not limited so we can re-enable any waiting listener */
|
||||||
dequeue_proxy_listeners(p);
|
dequeue_proxy_listeners(p, 0);
|
||||||
out:
|
out:
|
||||||
t->expire = next;
|
t->expire = next;
|
||||||
task_queue(t);
|
task_queue(t);
|
||||||
@ -3041,7 +3041,7 @@ static int cli_parse_set_maxconn_frontend(char **args, char *payload, struct app
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (px->maxconn > px->feconn)
|
if (px->maxconn > px->feconn)
|
||||||
dequeue_proxy_listeners(px);
|
dequeue_proxy_listeners(px, 1);
|
||||||
|
|
||||||
HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock);
|
HA_RWLOCK_WRUNLOCK(PROXY_LOCK, &px->lock);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user