dwh0403 发表于 2010-7-16 09:28:37

多线程下ACE_LOG析构异常问题

本帖最后由 dwh0403 于 2010-7-16 09:38 编辑

测试多线程日志的问题,ACE5.7.9 + WIN7 + VS2005
测试代码:

int ACE_TMAIN(int argc, ACE_TCHAR *argv[])
{
int thread_num = 10;
int flag = THR_NEW_LWP | THR_DETACHED |THR_INHERIT_SCHED; // 我故意设置成THR_DETACHED的

CTestLogThread task;
task.open(thread_num, flag);

ACE_OS::sleep(5);
ACE_Thread_Manager::instance()->cancel_all();
ACE_Thread_Manager::instance()->wait();

return 0;
}

class CTestLogThread: public ACE_Task<ACE_NULL_SYNCH>
{
public:
int open(int thread_num = 1, int thread_flag = THR_NEW_LWP | THR_INHERIT_SCHED);
virtual int svc (void);
};

int CTestLogThread: open(int thread_num, int thread_flag)
{
// Create worker threads.
if (this->activate (thread_flag, thread_num) == -1)
ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("activate failed")), -1);
return 0;
}
int CTestLogThread::svc()
{
ACE_LOG_MSG->enable_debug_messages();
for (int i = 0; i < 1000000; i++)
{
if (ACE_Thread_Manager::instance()->testcancel(ACE_OS::thr_self()))
{
   ACE_DEBUG((LM_DEBUG, "(%t) cancelled by manager\n"));
   return 0;
}
ACE_DEBUG((LM_DEBUG, ACE_TEXT("\n]%D@(%t)@@[%d]\n"), i));
}
return 0;
}

测试过程中会偶尔出现程序非法关闭,问题在于
ACE_Log_Msg::~ACE_Log_Msg (void)函数中的
{
.........
{
    ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
                     *ACE_Log_Msg_Manager::get_lock ()));
    instance_count = --instance_count_;
}

// If this is the last instance then cleanup.Only the last
// thread to destroy its ACE_Log_Msg instance should execute
// this block.
if (instance_count == 0) // 调试代码显示代码到了此处,但是在此以后才调用了(也可能为调试器显示有误)
// ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,*ACE_Log_Msg_Manager::get_lock ()));   的释放函数
{
      // Destroy the message queue instance.
      if (ACE_Log_Msg_Manager::log_backend_ != 0)
      ACE_Log_Msg_Manager::log_backend_->close ();
   ...................
}
释放该ACE_Recursive_Thread_Mutex时候出现异常,最终调用的为调用ACE_OS::thread_mutex_unlock (m);时候m为无效的指针。

该问题很难重现,一般要手工实验很多次才会出现一次,哪位有没有碰到过这种问题,有什么好的建议没有?

winston 发表于 2010-7-16 11:25:55

以前记得有人发现过这个问题,好像是个bug,你搜索一下论坛找找。

modern 发表于 2010-7-21 09:48:34

析构的时的崩溃时发生的哪个线程?
主线程还是工作线程?
印象里ACE_Log_Msg是一个线程一个实例。
贴一些更为详细的信息出来,比如堆栈,线程等

freeeyes 发表于 2010-7-21 10:01:03

感觉可能被双删除引起的BUG,我以前也遇到过类似的问题。
在多线程调用下,引用计数器可能会出现判断错误。
你开了一个10个线程的线程池,是否可以尝试在svc里面增加一个ACE_Recursive_Thread_Mutex锁,即
ACE_Recursive_Thread_Mutex m_ThreadWriteLock

m_ThreadWriteLock.acquire();
。。。//这里是你的ACE_Log_Msg操作
m_ThreadWriteLock.release();

dwh0403 发表于 2010-7-21 14:46:22

析构的时候,错误显示的是工作线程,准确说最后一个工作线程析构的时候。这个问题比较难重现,出现概率不等。最近在ACE Bug列表中看到ACE_TSS好像存在问题,不知道是否是这个问题引起的,ACE TSS的bug见http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=3539。

dwh0403 发表于 2010-7-21 14:47:30

感觉可能被双删除引起的BUG,我以前也遇到过类似的问题。
在多线程调用下,引用计数器可能会出现判断错误。 ...
freeeyes 发表于 2010-7-21 10:01 http://www.acejoy.com/bbs/images/common/back.gif

LOG MSG对象写入文件的时候,会自动调用加锁操作。

dwh0403 发表于 2010-7-21 14:51:08

前几天看仔细看过 Singleton模式线程安全的实现,貌似ACE Double-Check Singleton也未必是线程安全的,很多问题也可能是这些地方导致的,只是举个例子。

dwh0403 发表于 2010-7-21 14:51:26

前几天看仔细看过 Singleton模式线程安全的实现,貌似ACE Double-Check Singleton也未必是线程安全的,很多问题也可能是这些地方导致的,只是举个例子。
页: [1]
查看完整版本: 多线程下ACE_LOG析构异常问题