From d2843eba6d939526eb3daef511099bed2d18dd2c Mon Sep 17 00:00:00 2001 From: Gurucharan Shetty Date: Tue, 7 Apr 2015 17:34:27 -0700 Subject: [PATCH] ovs_threads: Avoid running pthread destructors from main thread exit. Windows uses pthreads-win32 library to provide the Linux pthread functionality. It is observed that when the main thread calls a pthread destructor after it exits, undefined behavior is seen (e.g., junk values in data, causing pthread deadlocks). Similar behavior has been seen by other people as seen in the following email thread: https://sourceware.org/ml/pthreads-win32/2003/msg00001.html To avoid this, this commit de-registers the thread destructor when the main thread exits (via the atexit handler). Signed-off-by: Gurucharan Shetty Acked-by: Ben Pfaff --- lib/ovs-rcu.c | 14 ++++++++++++++ lib/ovs-thread.c | 15 +++++++++++++++ tests/test-atomic.c | 2 ++ 3 files changed, 31 insertions(+) diff --git a/lib/ovs-rcu.c b/lib/ovs-rcu.c index 76659bbe0..e0634cfab 100644 --- a/lib/ovs-rcu.c +++ b/lib/ovs-rcu.c @@ -16,6 +16,7 @@ #include #include "ovs-rcu.h" +#include "fatal-signal.h" #include "guarded-list.h" #include "list.h" #include "ovs-thread.h" @@ -313,6 +314,18 @@ ovsrcu_thread_exit_cb(void *perthread) ovsrcu_unregister__(perthread); } +/* Cancels the callback to ovsrcu_thread_exit_cb(). + * + * Cancelling the call to the destructor during the main thread exit + * is needed while using pthreads-win32 library in Windows. It has been + * observed that in pthreads-win32, a call to the destructor during + * main thread exit causes undefined behavior. */ +static void +ovsrcu_cancel_thread_exit_cb(void *aux OVS_UNUSED) +{ + pthread_setspecific(perthread_key, NULL); +} + static void ovsrcu_init_module(void) { @@ -320,6 +333,7 @@ ovsrcu_init_module(void) if (ovsthread_once_start(&once)) { global_seqno = seq_create(); xpthread_key_create(&perthread_key, ovsrcu_thread_exit_cb); + fatal_signal_add_hook(ovsrcu_cancel_thread_exit_cb, NULL, NULL, true); list_init(&ovsrcu_threads); ovs_mutex_init(&ovsrcu_threads_mutex); diff --git a/lib/ovs-thread.c b/lib/ovs-thread.c index 416109563..b2d05a6cb 100644 --- a/lib/ovs-thread.c +++ b/lib/ovs-thread.c @@ -24,6 +24,7 @@ #include #include #include "compiler.h" +#include "fatal-signal.h" #include "hash.h" #include "list.h" #include "netdev-dpdk.h" @@ -668,6 +669,18 @@ ovsthread_key_destruct__(void *slots_) free(slots); } +/* Cancels the callback to ovsthread_key_destruct__(). + * + * Cancelling the call to the destructor during the main thread exit + * is needed while using pthreads-win32 library in Windows. It has been + * observed that in pthreads-win32, a call to the destructor during + * main thread exit causes undefined behavior. */ +static void +ovsthread_cancel_ovsthread_key_destruct__(void *aux OVS_UNUSED) +{ + pthread_setspecific(tsd_key, NULL); +} + /* Initializes '*keyp' as a thread-specific data key. The data items are * initially null in all threads. * @@ -684,6 +697,8 @@ ovsthread_key_create(ovsthread_key_t *keyp, void (*destructor)(void *)) if (ovsthread_once_start(&once)) { xpthread_key_create(&tsd_key, ovsthread_key_destruct__); + fatal_signal_add_hook(ovsthread_cancel_ovsthread_key_destruct__, + NULL, NULL, true); ovsthread_once_done(&once); } diff --git a/tests/test-atomic.c b/tests/test-atomic.c index 50b3b7a9e..2af6a2649 100644 --- a/tests/test-atomic.c +++ b/tests/test-atomic.c @@ -16,6 +16,7 @@ #include #undef NDEBUG +#include "fatal-signal.h" #include "ovs-atomic.h" #include "ovstest.h" #include "ovs-thread.h" @@ -413,6 +414,7 @@ test_atomic_seq_cst(void) static void test_atomic_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) { + fatal_signal_init(); test_atomic_plain(); test_atomic_relaxed(); test_atomic_consume(); -- 2.20.1