mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-21 14:35:45 +00:00
BUG/MEDIUM: splice/threads: pipe reuse list was not protected.
The list is now protected using a global spinlock.
This commit is contained in:
parent
926fa4c098
commit
d8b3b65faa
@ -174,6 +174,7 @@ enum lock_label {
|
|||||||
DNS_LOCK,
|
DNS_LOCK,
|
||||||
PID_LIST_LOCK,
|
PID_LIST_LOCK,
|
||||||
EMAIL_ALERTS_LOCK,
|
EMAIL_ALERTS_LOCK,
|
||||||
|
PIPES_LOCK,
|
||||||
LOCK_LABELS
|
LOCK_LABELS
|
||||||
};
|
};
|
||||||
struct lock_stat {
|
struct lock_stat {
|
||||||
@ -262,7 +263,8 @@ static inline void show_lock_stats()
|
|||||||
"UPDATED_SERVERS", "LBPRM", "SIGNALS", "STK_TABLE", "STK_SESS",
|
"UPDATED_SERVERS", "LBPRM", "SIGNALS", "STK_TABLE", "STK_SESS",
|
||||||
"APPLETS", "PEER", "BUF_WQ", "STREAMS", "SSL", "SSL_GEN_CERTS",
|
"APPLETS", "PEER", "BUF_WQ", "STREAMS", "SSL", "SSL_GEN_CERTS",
|
||||||
"PATREF", "PATEXP", "PATLRU", "VARS", "COMP_POOL", "LUA",
|
"PATREF", "PATEXP", "PATLRU", "VARS", "COMP_POOL", "LUA",
|
||||||
"NOTIF", "SPOE_APPLET", "DNS", "PID_LIST", "EMAIL_ALERTS" };
|
"NOTIF", "SPOE_APPLET", "DNS", "PID_LIST", "EMAIL_ALERTS",
|
||||||
|
"PIPES" };
|
||||||
int lbl;
|
int lbl;
|
||||||
|
|
||||||
for (lbl = 0; lbl < LOCK_LABELS; lbl++) {
|
for (lbl = 0; lbl < LOCK_LABELS; lbl++) {
|
||||||
|
38
src/pipe.c
38
src/pipe.c
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
struct pool_head *pool2_pipe = NULL;
|
struct pool_head *pool2_pipe = NULL;
|
||||||
struct pipe *pipes_live = NULL; /* pipes which are still ready to use */
|
struct pipe *pipes_live = NULL; /* pipes which are still ready to use */
|
||||||
|
HA_SPINLOCK_T pipes_lock; /* lock used to protect pipes list */
|
||||||
int pipes_used = 0; /* # of pipes in use (2 fds each) */
|
int pipes_used = 0; /* # of pipes in use (2 fds each) */
|
||||||
int pipes_free = 0; /* # of pipes unused */
|
int pipes_free = 0; /* # of pipes unused */
|
||||||
|
|
||||||
@ -30,6 +31,7 @@ static void init_pipe()
|
|||||||
pool2_pipe = create_pool("pipe", sizeof(struct pipe), MEM_F_SHARED);
|
pool2_pipe = create_pool("pipe", sizeof(struct pipe), MEM_F_SHARED);
|
||||||
pipes_used = 0;
|
pipes_used = 0;
|
||||||
pipes_free = 0;
|
pipes_free = 0;
|
||||||
|
HA_SPIN_INIT(&pipes_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return a pre-allocated empty pipe. Try to allocate one if there isn't any
|
/* return a pre-allocated empty pipe. Try to allocate one if there isn't any
|
||||||
@ -37,27 +39,28 @@ static void init_pipe()
|
|||||||
*/
|
*/
|
||||||
struct pipe *get_pipe()
|
struct pipe *get_pipe()
|
||||||
{
|
{
|
||||||
struct pipe *ret;
|
struct pipe *ret = NULL;
|
||||||
int pipefd[2];
|
int pipefd[2];
|
||||||
|
|
||||||
|
HA_SPIN_LOCK(PIPES_LOCK, &pipes_lock);
|
||||||
if (likely(pipes_live)) {
|
if (likely(pipes_live)) {
|
||||||
ret = pipes_live;
|
ret = pipes_live;
|
||||||
pipes_live = pipes_live->next;
|
pipes_live = pipes_live->next;
|
||||||
pipes_free--;
|
pipes_free--;
|
||||||
pipes_used++;
|
pipes_used++;
|
||||||
return ret;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipes_used >= global.maxpipes)
|
if (pipes_used >= global.maxpipes)
|
||||||
return NULL;
|
goto out;
|
||||||
|
|
||||||
ret = pool_alloc2(pool2_pipe);
|
ret = pool_alloc2(pool2_pipe);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return NULL;
|
goto out;
|
||||||
|
|
||||||
if (pipe(pipefd) < 0) {
|
if (pipe(pipefd) < 0) {
|
||||||
pool_free2(pool2_pipe, ret);
|
pool_free2(pool2_pipe, ret);
|
||||||
return NULL;
|
goto out;
|
||||||
}
|
}
|
||||||
#ifdef F_SETPIPE_SZ
|
#ifdef F_SETPIPE_SZ
|
||||||
if (global.tune.pipesize)
|
if (global.tune.pipesize)
|
||||||
@ -68,18 +71,28 @@ struct pipe *get_pipe()
|
|||||||
ret->cons = pipefd[0];
|
ret->cons = pipefd[0];
|
||||||
ret->next = NULL;
|
ret->next = NULL;
|
||||||
pipes_used++;
|
pipes_used++;
|
||||||
|
out:
|
||||||
|
HA_SPIN_UNLOCK(PIPES_LOCK, &pipes_lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void inline __kill_pipe(struct pipe *p)
|
||||||
|
{
|
||||||
|
close(p->prod);
|
||||||
|
close(p->cons);
|
||||||
|
pool_free2(pool2_pipe, p);
|
||||||
|
pipes_used--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* destroy a pipe, possibly because an error was encountered on it. Its FDs
|
/* destroy a pipe, possibly because an error was encountered on it. Its FDs
|
||||||
* will be closed and it will not be reinjected into the live pool.
|
* will be closed and it will not be reinjected into the live pool.
|
||||||
*/
|
*/
|
||||||
void kill_pipe(struct pipe *p)
|
void kill_pipe(struct pipe *p)
|
||||||
{
|
{
|
||||||
close(p->prod);
|
HA_SPIN_LOCK(PIPES_LOCK, &pipes_lock);
|
||||||
close(p->cons);
|
__kill_pipe(p);
|
||||||
pool_free2(pool2_pipe, p);
|
HA_SPIN_UNLOCK(PIPES_LOCK, &pipes_lock);
|
||||||
pipes_used--;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,14 +102,17 @@ void kill_pipe(struct pipe *p)
|
|||||||
*/
|
*/
|
||||||
void put_pipe(struct pipe *p)
|
void put_pipe(struct pipe *p)
|
||||||
{
|
{
|
||||||
|
HA_SPIN_LOCK(PIPES_LOCK, &pipes_lock);
|
||||||
if (p->data) {
|
if (p->data) {
|
||||||
kill_pipe(p);
|
__kill_pipe(p);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
p->next = pipes_live;
|
p->next = pipes_live;
|
||||||
pipes_live = p;
|
pipes_live = p;
|
||||||
pipes_free++;
|
pipes_free++;
|
||||||
pipes_used--;
|
pipes_used--;
|
||||||
|
out:
|
||||||
|
HA_SPIN_UNLOCK(PIPES_LOCK, &pipes_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user