Revert "MEDIUM: queue: simplify again the process_srv_queue() API"

This reverts commit c83e45e9b0.

The recent changes since 5304669e1 MEDIUM: queue: make
pendconn_process_next_strm() only return the pendconn opened a tiny race
condition between stream_free() and process_srv_queue(), as the pendconn
is accessed outside of the lock, possibly while it's being freed. A
different approach is required.
This commit is contained in:
Willy Tarreau 2021-06-24 07:22:18 +02:00
parent 58f4dfb2b0
commit ccd85a3e08
7 changed files with 16 additions and 12 deletions

View File

@ -34,7 +34,7 @@ extern struct pool_head *pool_head_pendconn;
struct pendconn *pendconn_add(struct stream *strm);
int pendconn_dequeue(struct stream *strm);
void process_srv_queue(struct server *s);
void process_srv_queue(struct server *s, int server_locked);
unsigned int srv_dynamic_maxconn(const struct server *s);
int pendconn_redistribute(struct server *s);
int pendconn_grab_from_px(struct server *s);

View File

@ -339,7 +339,7 @@ static inline void stream_choose_redispatch(struct stream *s)
((s->be->lbprm.algo & BE_LB_KIND) == BE_LB_KIND_RR)))) {
sess_change_server(s, NULL);
if (may_dequeue_tasks(objt_server(s->target), s->be))
process_srv_queue(objt_server(s->target));
process_srv_queue(objt_server(s->target), 0);
s->flags &= ~(SF_DIRECT | SF_ASSIGNED | SF_ADDR_SET);
si->state = SI_ST_REQ;

View File

@ -818,7 +818,7 @@ out_ok:
sess_change_server(s, srv);
} else {
if (may_dequeue_tasks(conn_slot, s->be))
process_srv_queue(conn_slot);
process_srv_queue(conn_slot, 0);
}
}
@ -1830,7 +1830,7 @@ int srv_redispatch_connect(struct stream *s)
/* release other streams waiting for this server */
if (may_dequeue_tasks(srv, s->be))
process_srv_queue(srv);
process_srv_queue(srv, 0);
return 1;
}
/* if we get here, it's because we got SRV_STATUS_OK, which also
@ -1906,7 +1906,7 @@ void back_try_conn_req(struct stream *s)
/* release other streams waiting for this server */
sess_change_server(s, NULL);
if (may_dequeue_tasks(srv, s->be))
process_srv_queue(srv);
process_srv_queue(srv, 0);
/* Failed and not retryable. */
si_shutr(si);
@ -2234,7 +2234,7 @@ void back_handle_st_cer(struct stream *s)
_HA_ATOMIC_INC(&s->be->be_counters.failed_conns);
sess_change_server(s, NULL);
if (may_dequeue_tasks(objt_server(s->target), s->be))
process_srv_queue(objt_server(s->target));
process_srv_queue(objt_server(s->target), 0);
/* shutw is enough so stop a connecting socket */
si_shutw(si);

View File

@ -2565,7 +2565,7 @@ int pcli_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
HA_ATOMIC_DEC(&__objt_server(s->target)->cur_sess);
}
if (may_dequeue_tasks(__objt_server(s->target), be))
process_srv_queue(__objt_server(s->target));
process_srv_queue(__objt_server(s->target), 0);
}
s->target = NULL;

View File

@ -331,9 +331,10 @@ static struct pendconn *pendconn_process_next_strm(struct server *srv, struct pr
}
/* Manages a server's connection queue. This function will try to dequeue as
* many pending streams as possible, and wake them up.
* many pending streams as possible, and wake them up. <server_locked> must
* only be set if the caller already hold the server lock.
*/
void process_srv_queue(struct server *s)
void process_srv_queue(struct server *s, int server_locked)
{
struct proxy *p = s->proxy;
int done = 0;

View File

@ -1818,8 +1818,11 @@ const char *server_parse_maxconn_change_request(struct server *sv,
sv->maxconn = v;
}
/* server_parse_maxconn_change_request requires the server lock held.
* Specify it to process_srv_queue to prevent a deadlock.
*/
if (may_dequeue_tasks(sv, sv->proxy))
process_srv_queue(sv);
process_srv_queue(sv, 1);
return NULL;
}

View File

@ -623,7 +623,7 @@ static void stream_free(struct stream *s)
_HA_ATOMIC_DEC(&__objt_server(s->target)->cur_sess);
}
if (may_dequeue_tasks(objt_server(s->target), s->be))
process_srv_queue(objt_server(s->target));
process_srv_queue(objt_server(s->target), 0);
}
if (unlikely(s->srv_conn)) {
@ -1815,7 +1815,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
}
sess_change_server(s, NULL);
if (may_dequeue_tasks(srv, s->be))
process_srv_queue(srv);
process_srv_queue(srv, 0);
}
}