- Add new patches (see https://www.haproxy.org/bugs/bugs-1.8.19.html) - Raise PKG_RELEASE to 4 Signed-off-by: Christian Lachner <gladiac@gmail.com>
168 lines
5.5 KiB
Diff
168 lines
5.5 KiB
Diff
commit 3bb33335816c1c9549d21bcc14bed29519b938a3
|
|
Author: Emeric Brun <ebrun@haproxy.com>
|
|
Date: Tue Apr 2 17:22:01 2019 +0200
|
|
|
|
BUG/MEDIUM: peers: fix a case where peer session is not cleanly reset on release.
|
|
|
|
The deinit took place in only peer_session_release, but in the a case of a
|
|
previous call to peer_session_forceshutdown, the session cursors
|
|
won't be reset, resulting in a bad state for new session of the same
|
|
peer. For instance, a table definition message could be dropped and
|
|
so all update messages will be dropped by the remote peer.
|
|
|
|
This patch move the deinit processing directly in the force shutdown
|
|
funtion. Killed session remains in "ST_END" state but ref on peer was
|
|
reset to NULL and deinit will be skipped on session release function.
|
|
|
|
The session release continue to assure the deinit for "active" sessions.
|
|
|
|
This patch should be backported on all stable version since proto
|
|
peers v2.
|
|
|
|
(cherry picked from commit 9ef2ad7844e577b505019695c59284f4a439fc33)
|
|
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
|
|
(cherry picked from commit 14831989a081f3944cf891afd56e6d9f6086c3ed)
|
|
[cf: global variabled connected_peers and active_peers don't exist in 1.8]
|
|
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
|
|
|
|
diff --git a/src/peers.c b/src/peers.c
|
|
index 465ffe85..d7dc51d8 100644
|
|
--- a/src/peers.c
|
|
+++ b/src/peers.c
|
|
@@ -172,7 +172,7 @@ enum {
|
|
#define PEER_DWNGRD_MINOR_VER 0
|
|
|
|
struct peers *cfg_peers = NULL;
|
|
-static void peer_session_forceshutdown(struct appctx *appctx);
|
|
+static void peer_session_forceshutdown(struct peer *peer);
|
|
|
|
/* This function encode an uint64 to 'dynamic' length format.
|
|
The encoded value is written at address *str, and the
|
|
@@ -492,15 +492,53 @@ static int peer_prepare_ackmsg(struct shared_table *st, char *msg, size_t size)
|
|
return (cursor - msg) + datalen;
|
|
}
|
|
|
|
+/*
|
|
+ * Function to deinit connected peer
|
|
+ */
|
|
+void __peer_session_deinit(struct peer *peer)
|
|
+{
|
|
+ struct stream_interface *si;
|
|
+ struct stream *s;
|
|
+ struct peers *peers;
|
|
+
|
|
+ if (!peer->appctx)
|
|
+ return;
|
|
+
|
|
+ si = peer->appctx->owner;
|
|
+ if (!si)
|
|
+ return;
|
|
+
|
|
+ s = si_strm(si);
|
|
+ if (!s)
|
|
+ return;
|
|
+
|
|
+ peers = strm_fe(s)->parent;
|
|
+ if (!peers)
|
|
+ return;
|
|
+
|
|
+ /* Re-init current table pointers to force announcement on re-connect */
|
|
+ peer->remote_table = peer->last_local_table = NULL;
|
|
+ peer->appctx = NULL;
|
|
+ if (peer->flags & PEER_F_LEARN_ASSIGN) {
|
|
+ /* unassign current peer for learning */
|
|
+ peer->flags &= ~(PEER_F_LEARN_ASSIGN);
|
|
+ peers->flags &= ~(PEERS_F_RESYNC_ASSIGN|PEERS_F_RESYNC_PROCESS);
|
|
+
|
|
+ /* reschedule a resync */
|
|
+ peers->resync_timeout = tick_add(now_ms, MS_TO_TICKS(5000));
|
|
+ }
|
|
+ /* reset teaching and learning flags to 0 */
|
|
+ peer->flags &= PEER_TEACH_RESET;
|
|
+ peer->flags &= PEER_LEARN_RESET;
|
|
+ task_wakeup(peers->sync_task, TASK_WOKEN_MSG);
|
|
+}
|
|
+
|
|
/*
|
|
* Callback to release a session with a peer
|
|
*/
|
|
static void peer_session_release(struct appctx *appctx)
|
|
{
|
|
- struct stream_interface *si = appctx->owner;
|
|
- struct stream *s = si_strm(si);
|
|
struct peer *peer = appctx->ctx.peers.ptr;
|
|
- struct peers *peers = strm_fe(s)->parent;
|
|
|
|
/* appctx->ctx.peers.ptr is not a peer session */
|
|
if (appctx->st0 < PEER_SESS_ST_SENDSUCCESS)
|
|
@@ -509,24 +547,9 @@ static void peer_session_release(struct appctx *appctx)
|
|
/* peer session identified */
|
|
if (peer) {
|
|
HA_SPIN_LOCK(PEER_LOCK, &peer->lock);
|
|
- if (peer->appctx == appctx) {
|
|
- /* Re-init current table pointers to force announcement on re-connect */
|
|
- peer->remote_table = peer->last_local_table = NULL;
|
|
- peer->appctx = NULL;
|
|
- if (peer->flags & PEER_F_LEARN_ASSIGN) {
|
|
- /* unassign current peer for learning */
|
|
- peer->flags &= ~(PEER_F_LEARN_ASSIGN);
|
|
- peers->flags &= ~(PEERS_F_RESYNC_ASSIGN|PEERS_F_RESYNC_PROCESS);
|
|
-
|
|
- /* reschedule a resync */
|
|
- peers->resync_timeout = tick_add(now_ms, MS_TO_TICKS(5000));
|
|
- }
|
|
- /* reset teaching and learning flags to 0 */
|
|
- peer->flags &= PEER_TEACH_RESET;
|
|
- peer->flags &= PEER_LEARN_RESET;
|
|
- }
|
|
+ if (peer->appctx == appctx)
|
|
+ __peer_session_deinit(peer);
|
|
HA_SPIN_UNLOCK(PEER_LOCK, &peer->lock);
|
|
- task_wakeup(peers->sync_task, TASK_WOKEN_MSG);
|
|
}
|
|
}
|
|
|
|
@@ -704,7 +727,7 @@ switchstate:
|
|
* for a while.
|
|
*/
|
|
curpeer->reconnect = tick_add(now_ms, MS_TO_TICKS(50 + random() % 2000));
|
|
- peer_session_forceshutdown(curpeer->appctx);
|
|
+ peer_session_forceshutdown(curpeer);
|
|
}
|
|
if (maj_ver != (unsigned int)-1 && min_ver != (unsigned int)-1) {
|
|
if (min_ver == PEER_DWNGRD_MINOR_VER) {
|
|
@@ -1832,11 +1855,14 @@ static struct applet peer_applet = {
|
|
.release = peer_session_release,
|
|
};
|
|
|
|
+
|
|
/*
|
|
* Use this function to force a close of a peer session
|
|
*/
|
|
-static void peer_session_forceshutdown(struct appctx *appctx)
|
|
+static void peer_session_forceshutdown(struct peer *peer)
|
|
{
|
|
+ struct appctx *appctx = peer->appctx;
|
|
+
|
|
/* Note that the peer sessions which have just been created
|
|
* (->st0 == PEER_SESS_ST_CONNECT) must not
|
|
* be shutdown, if not, the TCP session will never be closed
|
|
@@ -1849,6 +1875,8 @@ static void peer_session_forceshutdown(struct appctx *appctx)
|
|
if (appctx->applet != &peer_applet)
|
|
return;
|
|
|
|
+ __peer_session_deinit(peer);
|
|
+
|
|
appctx->st0 = PEER_SESS_ST_END;
|
|
appctx_wakeup(appctx);
|
|
}
|
|
@@ -2094,8 +2122,7 @@ static struct task *process_peer_sync(struct task * task)
|
|
*/
|
|
ps->reconnect = tick_add(now_ms, MS_TO_TICKS(50 + random() % 2000));
|
|
if (ps->appctx) {
|
|
- peer_session_forceshutdown(ps->appctx);
|
|
- ps->appctx = NULL;
|
|
+ peer_session_forceshutdown(ps);
|
|
}
|
|
}
|
|
}
|