Skip to content

Commit

Permalink
ovs_threads: Avoid running pthread destructors from main thread exit.
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Ben Pfaff <[email protected]>
  • Loading branch information
shettyg committed May 27, 2015
1 parent 3b4099b commit d2843eb
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 0 deletions.
14 changes: 14 additions & 0 deletions lib/ovs-rcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <config.h>
#include "ovs-rcu.h"
#include "fatal-signal.h"
#include "guarded-list.h"
#include "list.h"
#include "ovs-thread.h"
Expand Down Expand Up @@ -313,13 +314,26 @@ 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)
{
static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
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);

Expand Down
15 changes: 15 additions & 0 deletions lib/ovs-thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <stdlib.h>
#include <unistd.h>
#include "compiler.h"
#include "fatal-signal.h"
#include "hash.h"
#include "list.h"
#include "netdev-dpdk.h"
Expand Down Expand Up @@ -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.
*
Expand All @@ -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);
}

Expand Down
2 changes: 2 additions & 0 deletions tests/test-atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <config.h>
#undef NDEBUG
#include "fatal-signal.h"
#include "ovs-atomic.h"
#include "ovstest.h"
#include "ovs-thread.h"
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit d2843eb

Please sign in to comment.