res_xmpp: Use incremental backoff when a read error occurs

If a read error occurs, we immediately attempt a reconnect without any
delay. Instead, let's sleep and backoff up to 60 seconds before we try
again.

ASTERISK-24712 #close
Reported by: Matthias Urlichs

Change-Id: I6fe10ef4734837727437beab715e336777f13f48
changes/03/5303/2
Sean Bright 9 years ago
parent 391c412c0e
commit cd93488a82

@ -3595,6 +3595,7 @@ int ast_xmpp_client_disconnect(struct ast_xmpp_client *client)
{ {
if ((client->thread != AST_PTHREADT_NULL) && !pthread_equal(pthread_self(), client->thread)) { if ((client->thread != AST_PTHREADT_NULL) && !pthread_equal(pthread_self(), client->thread)) {
xmpp_client_change_state(client, XMPP_STATE_DISCONNECTING); xmpp_client_change_state(client, XMPP_STATE_DISCONNECTING);
pthread_cancel(client->thread);
pthread_join(client->thread, NULL); pthread_join(client->thread, NULL);
client->thread = AST_PTHREADT_NULL; client->thread = AST_PTHREADT_NULL;
} }
@ -3774,11 +3775,26 @@ static int xmpp_client_receive(struct ast_xmpp_client *client, unsigned int time
return IKS_OK; return IKS_OK;
} }
static void sleep_with_backoff(unsigned int *sleep_time)
{
/* We're OK with our thread dying here */
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
sleep(*sleep_time);
*sleep_time = MIN(60, *sleep_time * 2);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
}
/*! \brief XMPP client connection thread */ /*! \brief XMPP client connection thread */
static void *xmpp_client_thread(void *data) static void *xmpp_client_thread(void *data)
{ {
struct ast_xmpp_client *client = data; struct ast_xmpp_client *client = data;
int res = IKS_NET_RWERR; int res = IKS_NET_RWERR;
unsigned int sleep_time = 1;
/* We only allow cancellation while sleeping */
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
do { do {
if (client->state == XMPP_STATE_DISCONNECTING) { if (client->state == XMPP_STATE_DISCONNECTING) {
@ -3789,7 +3805,7 @@ static void *xmpp_client_thread(void *data)
if (res == IKS_NET_RWERR || client->timeout == 0) { if (res == IKS_NET_RWERR || client->timeout == 0) {
ast_debug(3, "[%s] Connecting\n", client->name); ast_debug(3, "[%s] Connecting\n", client->name);
if ((res = xmpp_client_reconnect(client)) != IKS_OK) { if ((res = xmpp_client_reconnect(client)) != IKS_OK) {
sleep(4); sleep_with_backoff(&sleep_time);
res = IKS_NET_RWERR; res = IKS_NET_RWERR;
} }
continue; continue;
@ -3828,6 +3844,8 @@ static void *xmpp_client_thread(void *data)
} }
} else if (res == IKS_NET_RWERR) { } else if (res == IKS_NET_RWERR) {
ast_log(LOG_WARNING, "[%s] Socket read error\n", client->name); ast_log(LOG_WARNING, "[%s] Socket read error\n", client->name);
ast_xmpp_client_disconnect(client);
sleep_with_backoff(&sleep_time);
} else if (res == IKS_NET_NOSOCK) { } else if (res == IKS_NET_NOSOCK) {
ast_log(LOG_WARNING, "[%s] No socket\n", client->name); ast_log(LOG_WARNING, "[%s] No socket\n", client->name);
} else if (res == IKS_NET_NOCONN) { } else if (res == IKS_NET_NOCONN) {
@ -3840,6 +3858,8 @@ static void *xmpp_client_thread(void *data)
ast_log(LOG_WARNING, "[%s] Dropped?\n", client->name); ast_log(LOG_WARNING, "[%s] Dropped?\n", client->name);
} else if (res == IKS_NET_UNKNOWN) { } else if (res == IKS_NET_UNKNOWN) {
ast_debug(5, "[%s] Unknown\n", client->name); ast_debug(5, "[%s] Unknown\n", client->name);
} else if (res == IKS_OK) {
sleep_time = 1;
} }
} while (1); } while (1);

Loading…
Cancel
Save