From 8dba589c3665a3f4925bfca2844e973771bda1cc Mon Sep 17 00:00:00 2001 From: "Tahhan, Maryam" Date: Wed, 29 Nov 2017 12:50:18 +0000 Subject: [PATCH] utils_ovs: fix #2574 Poll thread was trying to reconnect after event thread was terminated. Change-Id: I48bf196302139ddf99bb96b49a6c3b4ede345240 Signed-off-by: Mytnyk, Volodymyr --- src/ovs_stats.c | 2 +- src/utils_ovs.c | 50 +++++++++++++++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/ovs_stats.c b/src/ovs_stats.c index e2103744..e027845e 100644 --- a/src/ovs_stats.c +++ b/src/ovs_stats.c @@ -974,9 +974,9 @@ static int ovs_stats_plugin_read(__attribute__((unused)) user_data_t *ud) { /* Shutdown OvS Stats plugin */ static int ovs_stats_plugin_shutdown(void) { - pthread_mutex_lock(&g_stats_lock); DEBUG("OvS Statistics plugin shutting down"); ovs_db_destroy(g_ovs_db); + pthread_mutex_lock(&g_stats_lock); ovs_stats_free_bridge_list(g_bridge_list_head); ovs_stats_free_bridge_list(g_monitored_bridge_list_head); ovs_stats_free_port_list(g_port_list_head); diff --git a/src/utils_ovs.c b/src/utils_ovs.c index 3c448e3e..4f487550 100644 --- a/src/utils_ovs.c +++ b/src/utils_ovs.c @@ -105,6 +105,7 @@ #define OVS_DB_POLL_READ_BLOCK_SIZE 512 /* read block size (bytes) */ #define OVS_DB_DEFAULT_DB_NAME "Open_vSwitch" +#define OVS_DB_EVENT_NONE 0 #define OVS_DB_EVENT_TIMEOUT 5 /* event thread timeout (sec) */ #define OVS_DB_EVENT_TERMINATE 1 #define OVS_DB_EVENT_CONN_ESTABLISHED 2 @@ -763,8 +764,8 @@ static void ovs_db_reconnect(ovs_db_t *pdb) { OVS_DEBUG("connect(): %s [family=%d]", errbuff, rp->ai_family); } else { /* send notification to event thread */ - ovs_db_event_post(pdb, OVS_DB_EVENT_CONN_ESTABLISHED); pdb->sock = sock; + ovs_db_event_post(pdb, OVS_DB_EVENT_CONN_ESTABLISHED); break; } } @@ -868,26 +869,30 @@ static void *ovs_event_worker(void *arg) { ts.tv_sec += (OVS_DB_EVENT_TIMEOUT); int ret = pthread_cond_timedwait(&pdb->event_thread.cond, &pdb->event_thread.mutex, &ts); - if (!ret) { + if (!ret || ret == ETIMEDOUT) { /* handle the event */ OVS_DEBUG("handle event %d", pdb->event_thread.value); switch (pdb->event_thread.value) { case OVS_DB_EVENT_CONN_ESTABLISHED: if (pdb->cb.post_conn_init) pdb->cb.post_conn_init(pdb); + /* reset event */ + pdb->event_thread.value = OVS_DB_EVENT_NONE; break; case OVS_DB_EVENT_CONN_TERMINATED: if (pdb->cb.post_conn_terminate) pdb->cb.post_conn_terminate(); + /* reset event */ + pdb->event_thread.value = OVS_DB_EVENT_NONE; + break; + case OVS_DB_EVENT_NONE: + /* wait timeout */ + OVS_DEBUG("no event received (timeout)"); break; default: OVS_DEBUG("unknown event received"); break; } - } else if (ret == ETIMEDOUT) { - /* wait timeout */ - OVS_DEBUG("no event received (timeout)"); - continue; } else { /* unexpected error */ OVS_ERROR("pthread_cond_timedwait() failed"); @@ -933,11 +938,10 @@ static int ovs_db_event_thread_init(ovs_db_t *pdb) { return 0; } -/* Destroy EVENT thread */ -/* XXX: Must hold pdb->mutex when calling! */ -static int ovs_db_event_thread_destroy(ovs_db_t *pdb) { +/* Terminate EVENT thread */ +static int ovs_db_event_thread_terminate(ovs_db_t *pdb) { if (pthread_equal(pdb->event_thread.tid, (pthread_t){0})) { - /* already destroyed */ + /* already terminated */ return 0; } ovs_db_event_post(pdb, OVS_DB_EVENT_TERMINATE); @@ -947,11 +951,16 @@ static int ovs_db_event_thread_destroy(ovs_db_t *pdb) { * performs some task (handles event) and releases it when * while sleeping. Thus, if event thread exits, the mutex * remains locked */ + pdb->event_thread.tid = (pthread_t){0}; pthread_mutex_unlock(&pdb->event_thread.mutex); + return 0; +} + +/* Destroy EVENT thread private data */ +static void ovs_db_event_thread_data_destroy(ovs_db_t *pdb) { + /* destroy mutex */ pthread_mutex_destroy(&pdb->event_thread.mutex); pthread_cond_destroy(&pdb->event_thread.cond); - pdb->event_thread.tid = (pthread_t){0}; - return 0; } /* Initialize POLL thread */ @@ -1253,23 +1262,26 @@ int ovs_db_destroy(ovs_db_t *pdb) { if (pdb == NULL) return -1; + /* stop event thread */ + if (ovs_db_event_thread_terminate(pdb) < 0) { + OVS_ERROR("stop event thread failed"); + ovs_db_ret = -1; + } + /* try to lock the structure before releasing */ if ((ret = pthread_mutex_lock(&pdb->mutex))) { OVS_ERROR("pthread_mutex_lock() DB mutex lock failed (%d)", ret); return -1; } - /* stop poll thread */ - if (ovs_db_event_thread_destroy(pdb) < 0) { + /* stop poll thread and destroy thread's private data */ + if (ovs_db_poll_thread_destroy(pdb) < 0) { OVS_ERROR("destroy poll thread failed"); ovs_db_ret = -1; } - /* stop event thread */ - if (ovs_db_poll_thread_destroy(pdb) < 0) { - OVS_ERROR("stop event thread failed"); - ovs_db_ret = -1; - } + /* destroy event thread private data */ + ovs_db_event_thread_data_destroy(pdb); pthread_mutex_unlock(&pdb->mutex); -- 2.11.0