0fc5fb1636ac96c84aab11c0a454a17eacf8c91a
[feed/packages.git] /
1 commit 5d60902ec7883bb05927c648638a009eb930acc7
2 Author: Willy Tarreau <w@1wt.eu>
3 Date: Mon May 27 10:17:05 2019 +0200
4
5 BUG/MAJOR: lb/threads: make sure the avoided server is not full on second pass
6
7 In fwrr_get_next_server(), we optionally pass a server to avoid. It
8 usually points to the current server during a redispatch operation. If
9 this server is usable, an "avoided" pointer is set and we continue to
10 look for another server. If in the end no other server is found, then
11 we fall back to this avoided one, which is still better than nothing.
12
13 The problem that may arise with threads is that in the mean time, this
14 avoided server might have received extra connections and might not be
15 usable anymore. This causes it to be queued a second time in the "full"
16 list and the loop to search for a server again, ending up on this one
17 again and so on.
18
19 This patch makes sure that we break out of the loop when we have to
20 pick the avoided server. It's probably what the code intended to do
21 as the current break statement causes fwrr_update_position() and
22 fwrr_dequeue_srv() to be called again on the avoided server.
23
24 It must be backported to 1.9 and 1.8, and seems appropriate for older
25 versions though it's unclear what the impact of this bug might be
26 there since the race doesn't exist and we're left with the double
27 update of the server's position.
28
29 (cherry picked from commit b6195ef2a6b0cb3f68bc34735313daa640ab3e92)
30 Signed-off-by: Willy Tarreau <w@1wt.eu>
31 (cherry picked from commit 7df15f275af90110e6ab4ec75065cbfabdf764ec)
32 Signed-off-by: Willy Tarreau <w@1wt.eu>
33
34 diff --git a/src/lb_fwrr.c b/src/lb_fwrr.c
35 index cba7db5f..33181b46 100644
36 --- a/src/lb_fwrr.c
37 +++ b/src/lb_fwrr.c
38 @@ -504,7 +504,7 @@ struct server *fwrr_get_next_server(struct proxy *p, struct server *srvtoavoid)
39 if (switched) {
40 if (avoided) {
41 srv = avoided;
42 - break;
43 + goto take_this_one;
44 }
45 goto requeue_servers;
46 }
47 @@ -534,6 +534,7 @@ struct server *fwrr_get_next_server(struct proxy *p, struct server *srvtoavoid)
48 full = srv;
49 }
50
51 + take_this_one:
52 /* OK, we got the best server, let's update it */
53 fwrr_queue_srv(srv);
54