Posix Thread: Removes the setting of the run function to NULL which could cause data race.
BUG=http://code.google.com/p/chromium/issues/detail?id=103711 TESTED=Code analysis (no tools) Review URL: https://webrtc-codereview.appspot.com/1008006 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3388 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
4ad64458cb
commit
a3e6bec23a
@ -52,8 +52,8 @@ class ThreadWrapper {
|
|||||||
// prio Thread priority. May require root/admin rights.
|
// prio Thread priority. May require root/admin rights.
|
||||||
// thread_name NULL terminated thread name, will be visable in the Windows
|
// thread_name NULL terminated thread name, will be visable in the Windows
|
||||||
// debugger.
|
// debugger.
|
||||||
static ThreadWrapper* CreateThread(ThreadRunFunction func = 0,
|
static ThreadWrapper* CreateThread(ThreadRunFunction func,
|
||||||
ThreadObj obj = 0,
|
ThreadObj obj,
|
||||||
ThreadPriority prio = kNormalPriority,
|
ThreadPriority prio = kNormalPriority,
|
||||||
const char* thread_name = 0);
|
const char* thread_name = 0);
|
||||||
|
|
||||||
|
@ -97,8 +97,7 @@ extern "C"
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadWrapper* ThreadPosix::Create(ThreadRunFunction func,
|
ThreadWrapper* ThreadPosix::Create(ThreadRunFunction func, ThreadObj obj,
|
||||||
ThreadObj obj,
|
|
||||||
ThreadPriority prio,
|
ThreadPriority prio,
|
||||||
const char* thread_name) {
|
const char* thread_name) {
|
||||||
ThreadPosix* ptr = new ThreadPosix(func, obj, prio, thread_name);
|
ThreadPosix* ptr = new ThreadPosix(func, obj, prio, thread_name);
|
||||||
@ -174,9 +173,6 @@ ThreadPosix::~ThreadPosix() {
|
|||||||
|
|
||||||
bool ThreadPosix::Start(unsigned int& thread_id)
|
bool ThreadPosix::Start(unsigned int& thread_id)
|
||||||
{
|
{
|
||||||
if (!run_function_) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int result = pthread_attr_setdetachstate(&attr_, PTHREAD_CREATE_DETACHED);
|
int result = pthread_attr_setdetachstate(&attr_, PTHREAD_CREATE_DETACHED);
|
||||||
// Set the stack stack size to 1M.
|
// Set the stack stack size to 1M.
|
||||||
result |= pthread_attr_setstacksize(&attr_, 1024 * 1024);
|
result |= pthread_attr_setstacksize(&attr_, 1024 * 1024);
|
||||||
@ -195,15 +191,17 @@ bool ThreadPosix::Start(unsigned int& thread_id)
|
|||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
CriticalSectionScoped cs(crit_state_);
|
||||||
|
dead_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Wait up to 10 seconds for the OS to call the callback function. Prevents
|
// Wait up to 10 seconds for the OS to call the callback function. Prevents
|
||||||
// race condition if Stop() is called too quickly after start.
|
// race condition if Stop() is called too quickly after start.
|
||||||
if (kEventSignaled != event_->Wait(WEBRTC_EVENT_10_SEC)) {
|
if (kEventSignaled != event_->Wait(WEBRTC_EVENT_10_SEC)) {
|
||||||
WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
|
WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
|
||||||
"posix thread event never triggered");
|
"posix thread event never triggered");
|
||||||
|
|
||||||
// Timed out. Something went wrong.
|
// Timed out. Something went wrong.
|
||||||
run_function_ = NULL;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +289,7 @@ bool ThreadPosix::Stop() {
|
|||||||
|
|
||||||
// TODO(hellner) why not use an event here?
|
// TODO(hellner) why not use an event here?
|
||||||
// Wait up to 10 seconds for the thread to terminate
|
// Wait up to 10 seconds for the thread to terminate
|
||||||
for (int i = 0; i < 1000 && !dead; i++) {
|
for (int i = 0; i < 1000 && !dead; ++i) {
|
||||||
timespec t;
|
timespec t;
|
||||||
t.tv_sec = 0;
|
t.tv_sec = 0;
|
||||||
t.tv_nsec = 10 * 1000 * 1000;
|
t.tv_nsec = 10 * 1000 * 1000;
|
||||||
@ -312,7 +310,6 @@ void ThreadPosix::Run() {
|
|||||||
{
|
{
|
||||||
CriticalSectionScoped cs(crit_state_);
|
CriticalSectionScoped cs(crit_state_);
|
||||||
alive_ = true;
|
alive_ = true;
|
||||||
dead_ = false;
|
|
||||||
}
|
}
|
||||||
#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
|
#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
|
||||||
pid_ = GetThreadId();
|
pid_ = GetThreadId();
|
||||||
@ -331,22 +328,15 @@ void ThreadPosix::Run() {
|
|||||||
"Thread without name started");
|
"Thread without name started");
|
||||||
}
|
}
|
||||||
bool alive = true;
|
bool alive = true;
|
||||||
do {
|
bool run = true;
|
||||||
if (run_function_) {
|
while (alive) {
|
||||||
if (!run_function_(obj_)) {
|
run = run_function_(obj_);
|
||||||
alive = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alive = false;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
CriticalSectionScoped cs(crit_state_);
|
CriticalSectionScoped cs(crit_state_);
|
||||||
if (!alive) {
|
if (!run) {
|
||||||
alive_ = false;
|
alive_ = false;
|
||||||
}
|
}
|
||||||
alive = alive_;
|
alive = alive_;
|
||||||
}
|
}
|
||||||
} while (alive);
|
|
||||||
|
|
||||||
if (set_thread_name_) {
|
if (set_thread_name_) {
|
||||||
// Don't set the name for the trace thread because it may cause a
|
// Don't set the name for the trace thread because it may cause a
|
||||||
|
@ -15,20 +15,13 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
TEST(ThreadTest, NullFunctionPointer) {
|
|
||||||
webrtc::scoped_ptr<ThreadWrapper> thread(
|
|
||||||
webrtc::ThreadWrapper::CreateThread());
|
|
||||||
unsigned int id = 42;
|
|
||||||
EXPECT_FALSE(thread->Start(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function that does nothing, and reports success.
|
// Function that does nothing, and reports success.
|
||||||
bool NullRunFunction(void* obj) {
|
bool NullRunFunction(void* obj) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ThreadTest, StartStop) {
|
TEST(ThreadTest, StartStop) {
|
||||||
ThreadWrapper* thread = ThreadWrapper::CreateThread(&NullRunFunction);
|
ThreadWrapper* thread = ThreadWrapper::CreateThread(&NullRunFunction, NULL);
|
||||||
unsigned int id = 42;
|
unsigned int id = 42;
|
||||||
ASSERT_TRUE(thread->Start(id));
|
ASSERT_TRUE(thread->Start(id));
|
||||||
EXPECT_TRUE(thread->Stop());
|
EXPECT_TRUE(thread->Stop());
|
||||||
|
Loading…
Reference in New Issue
Block a user