From: Tor Didriksen Date: July 23 2010 12:49pm Subject: bzr commit into mysql-next-mr-bugfixing branch (tor.didriksen:3321) Bug#55434 List-Archive: http://lists.mysql.com/commits/114222 X-Bug: 55434 Message-Id: <20100723125000.296483718@atum07.norway.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============3044576018546428488==" --===============3044576018546428488== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///export/home/didrik/repo/next-mr-bf-bug55434/ based on revid:alik@stripped 3321 Tor Didriksen 2010-07-23 Bug #55434 multithreaded gunit tests fail on windows On windows we need an open handle to the thread in order to join it. @ unittest/gunit/thread_utils.cc On windows: keep an open handle to a thread in order to join it safely. Use mysql_xxx() wrappers for pthread_xxx() functions. @ unittest/gunit/thread_utils.h Use mysql_mutex_t/mysql_cond_t rather than pthread_mutex_t/pthread_cond_t modified: unittest/gunit/thread_utils.cc unittest/gunit/thread_utils.h === modified file 'unittest/gunit/thread_utils.cc' --- a/unittest/gunit/thread_utils.cc 2010-05-21 13:02:27 +0000 +++ b/unittest/gunit/thread_utils.cc 2010-07-23 12:49:56 +0000 @@ -15,14 +15,41 @@ #include #include "thread_utils.h" +#include "mysql/psi/mysql_thread.h" namespace thread { +/* + On windows we need an open handle to the thread in order to join it. + The three instances of Notification are used as follows: + - The main thread starts sub-thread, waits for m_thread_started. + - The main thread picks up the thread id, and does OpenThread to get a handle. + - The main thread tells the sub-thread that it can continue + (notifies m_thread_continue) + - The main thread waits until the sub-thread is actually running + (waits for m_thread_running) before destroying all objects. + + All this is to work around a bug in pthread_create() in mysys/my_winthread, + which closes the thread handle (it has nowhere to store it). + When we later call pthread_join() we try to re-open a handle. + This will fail if the thread has already finished, and then the join will fail. + */ +class Thread_start_arg +{ +public: + Thread_start_arg(Thread *thread) : m_thread(thread) {} + + Notification m_thread_started; + Notification m_thread_continue; + Notification m_thread_running; + Thread *m_thread; +}; + namespace { void *thread_start_routine(void *arg) { - Thread *thread= (Thread*) arg; - Thread::run_wrapper(thread); + Thread_start_arg *start_arg= (Thread_start_arg*) arg; + Thread::run_wrapper(start_arg); return NULL; } @@ -38,56 +65,111 @@ void assert_false(int arg, int line) Thread::~Thread() { +#ifdef __WIN__ + if (m_thread_handle != NULL) + CloseHandle(m_thread_handle); +#endif } int Thread::start() { - return pthread_create(&m_thread_id, NULL, thread_start_routine, this); + Thread_start_arg start_arg(this); + const int retval= + pthread_create(&m_thread_id, NULL, thread_start_routine, &start_arg); + if (retval != 0) + { + ADD_FAILURE() << " could not start thread, errno: " << errno; + return retval; + } + + start_arg.m_thread_started.wait_for_notification(); +#ifdef __WIN__ + m_thread_handle= OpenThread(SYNCHRONIZE, FALSE, m_thread_id); + if (m_thread_handle == NULL) + { + DWORD lasterror= GetLastError(); + ADD_FAILURE() + << " could not open thread id " << m_thread_id + << " GetLastError: " << lasterror + ; + } +#endif + start_arg.m_thread_continue.notify(); + start_arg.m_thread_running.wait_for_notification(); + return retval; } +#ifdef __WIN__ void Thread::join() { - int failed= pthread_join(m_thread_id, NULL); - ASSERT_FALSE(failed); + DWORD ret= WaitForSingleObject(m_thread_handle, INFINITE); + if (ret != WAIT_OBJECT_0) + { + DWORD lasterror= GetLastError(); + ADD_FAILURE() + << " could not join thread id " << m_thread_id + << " handle " << m_thread_handle + << " GetLastError: " << lasterror + ; + } + CloseHandle(m_thread_handle); + m_thread_handle= NULL; +} +#else +void Thread::join() +{ + const int failed= pthread_join(m_thread_id, NULL); + if (failed) + { + ADD_FAILURE() + << " could not join thread id " << m_thread_id + << " failed: " << failed << " errno: " << errno + ; + } } +#endif -void Thread::run_wrapper(Thread *thread) +void Thread::run_wrapper(Thread_start_arg *start_arg) { const my_bool error= my_thread_init(); ASSERT_FALSE(error); + Thread *thread= start_arg->m_thread; + start_arg->m_thread_started.notify(); + start_arg->m_thread_continue.wait_for_notification(); + start_arg->m_thread_running.notify(); thread->run(); my_thread_end(); } -Mutex_lock::Mutex_lock(pthread_mutex_t *mutex) : m_mutex(mutex) +Mutex_lock::Mutex_lock(mysql_mutex_t *mutex) : m_mutex(mutex) { - pthread_mutex_lock(m_mutex); + mysql_mutex_lock(m_mutex); } Mutex_lock::~Mutex_lock() { - const int failed= pthread_mutex_unlock(m_mutex); + const int failed= mysql_mutex_unlock(m_mutex); LOCAL_ASSERT_FALSE(failed); } Notification::Notification() : m_notified(FALSE) { - const int failed1= pthread_cond_init(&m_cond, NULL); + const int failed1= mysql_cond_init(0, &m_cond, NULL); LOCAL_ASSERT_FALSE(failed1); - const int failed2= pthread_mutex_init(&m_mutex, MY_MUTEX_INIT_FAST); + const int failed2= mysql_mutex_init(0, &m_mutex, MY_MUTEX_INIT_FAST); LOCAL_ASSERT_FALSE(failed2); } Notification::~Notification() { - pthread_mutex_destroy(&m_mutex); - pthread_cond_destroy(&m_cond); + mysql_mutex_destroy(&m_mutex); + mysql_cond_destroy(&m_cond); } bool Notification::has_been_notified() @@ -101,7 +183,7 @@ void Notification::wait_for_notification Mutex_lock lock(&m_mutex); while (!m_notified) { - const int failed= pthread_cond_wait(&m_cond, &m_mutex); + const int failed= mysql_cond_wait(&m_cond, &m_mutex); ASSERT_FALSE(failed); } } @@ -110,7 +192,7 @@ void Notification::notify() { Mutex_lock lock(&m_mutex); m_notified= TRUE; - const int failed= pthread_cond_broadcast(&m_cond); + const int failed= mysql_cond_broadcast(&m_cond); ASSERT_FALSE(failed); } === modified file 'unittest/gunit/thread_utils.h' --- a/unittest/gunit/thread_utils.h 2010-03-19 11:46:14 +0000 +++ b/unittest/gunit/thread_utils.h 2010-07-23 12:49:56 +0000 @@ -21,6 +21,8 @@ namespace thread { +class Thread_start_arg; + /* An abstract class for creating/running/joining threads. Thread::start() will create a new pthread, and execute the run() function. @@ -28,7 +30,11 @@ namespace thread { class Thread { public: - Thread() : m_thread_id(0) {} + Thread() : m_thread_id(0) +#ifdef __WIN__ + , m_thread_handle(NULL) +#endif + {} virtual ~Thread(); /* @@ -51,7 +57,7 @@ public: Users should *not* call this function directly, they should rather invoke the start() function. */ - static void run_wrapper(Thread*); + static void run_wrapper(Thread_start_arg*); protected: /* @@ -63,6 +69,10 @@ protected: private: pthread_t m_thread_id; +#ifdef __WIN__ + // We need an open handle to the thread in order to join() it. + HANDLE m_thread_handle; +#endif Thread(const Thread&); /* Not copyable. */ void operator=(const Thread&); /* Not assignable. */ @@ -74,10 +84,10 @@ private: class Mutex_lock { public: - Mutex_lock(pthread_mutex_t *mutex); + Mutex_lock(mysql_mutex_t *mutex); ~Mutex_lock(); private: - pthread_mutex_t *m_mutex; + mysql_mutex_t *m_mutex; Mutex_lock(const Mutex_lock&); /* Not copyable. */ void operator=(const Mutex_lock&); /* Not assignable. */ @@ -96,8 +106,8 @@ public: void notify(); private: bool m_notified; - pthread_cond_t m_cond; - pthread_mutex_t m_mutex; + mysql_cond_t m_cond; + mysql_mutex_t m_mutex; Notification(const Notification&); /* Not copyable. */ void operator=(const Notification&); /* Not assignable. */ --===============3044576018546428488== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/tor.didriksen@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: tor.didriksen@stripped\ # 9edwzbvcelulide3 # target_branch: file:///export/home/didrik/repo/next-mr-bf-bug55434/ # testament_sha1: 5c59ce720664d8b45412408122f9138144be5493 # timestamp: 2010-07-23 14:50:00 +0200 # base_revision_id: alik@stripped # # Begin bundle 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 --===============3044576018546428488==--