1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
// $Id: Bug_2772_Regression_Test.cpp 91671 2010-09-08 18:39:23Z johnnyw $
// ============================================================================
//
// = LIBRARY
// tests
//
// = DESCRIPTION
// Test bug 2772 regression
//
// = AUTHOR
// Johnny Willemsen
//
// ============================================================================
#include "test_config.h"
#include "ace/Recursive_Thread_Mutex.h"
#include "ace/Condition_Recursive_Thread_Mutex.h"
#include "ace/Thread.h"
class ThreadTest
{
public:
ThreadTest();
~ThreadTest();
int run(bool doubleLock);
private:
static void * workerThreadWrapper(void *);
void workerThread();
ACE_Recursive_Thread_Mutex m_mutex;
ACE_Condition_Recursive_Thread_Mutex m_startedCondition;
ACE_Condition_Recursive_Thread_Mutex m_stopCondition;
bool m_workerRunning;
bool m_doubleLock;
};
ThreadTest::ThreadTest() :
m_startedCondition(m_mutex),
m_stopCondition(m_mutex),
m_workerRunning(false),
m_doubleLock(false)
{
}
ThreadTest::~ThreadTest()
{
}
int
ThreadTest::run(bool doubleLock)
{
ACE_hthread_t m_workerThreadHandle;
ACE_thread_t m_workerThreadId;
m_workerRunning = false;
m_doubleLock = doubleLock;
m_mutex.acquire();
// Start worker thread
int rval = ACE_Thread::spawn((ACE_THR_FUNC) workerThreadWrapper, this,
THR_JOINABLE | THR_NEW_LWP, &m_workerThreadId, &m_workerThreadHandle,
ACE_DEFAULT_THREAD_PRIORITY);
if (rval == -1)
{
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("%t Could not start worker thread!\n")),
1);
}
if (!m_workerRunning)
{
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("%t Waiting for worker thread to start running...\n")));
m_startedCondition.wait();
}
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("%t Worker thread is running...\n")));
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("%t Broadcasting STOP Condition...\n")));
m_stopCondition.broadcast();
m_mutex.release();
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("%t Joining worker thread...\n")));
ACE_Thread::join(m_workerThreadHandle);
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("%t Test finished...\n")));
return 0;
}
void* ThreadTest::workerThreadWrapper(void *data)
{
ThreadTest *thisPtr = reinterpret_cast<ThreadTest *>(data);
thisPtr->workerThread();
return 0;
}
void ThreadTest::workerThread()
{
m_mutex.acquire();
m_workerRunning = true;
m_startedCondition.broadcast();
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("%t Thread running, waiting for stop condition.\n")));
if (m_doubleLock)
{
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("%t Thread starting double acquire.\n")));
m_mutex.acquire();
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("%t Thread finished double acquire.\n")));
}
// Wait for the STOP condition to occur
m_stopCondition.wait();
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("%t Thread received stop condition, exiting.\n")));
if (m_doubleLock)
{
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("%t Thread starting double release.\n")));
m_mutex.release();
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("%t Thread finished double acquire.\n")));
}
m_mutex.release();
}
int
run_main (int, ACE_TCHAR *[])
{
ACE_START_TEST (ACE_TEXT ("Bug_2772_Regression_Test"));
int status = 0;
ThreadTest test;
// This test passes
ACE_DEBUG ((LM_DEBUG, "TEST 1 - Single Lock\n"));
ACE_DEBUG ((LM_DEBUG, "--------------------\n"));
status += test.run(false);
// This test hangs; m_stopCondition.wait() in the worker thread
// doesn't unlock the mutex twice and thus a deadlock occurs
ACE_DEBUG ((LM_DEBUG, "TEST 2 - Double Lock\n"));
ACE_DEBUG ((LM_DEBUG, "--------------------\n"));
status += test.run(true);
ACE_END_TEST;
return status;
}
|