多线程下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为无效的指针。
该问题很难重现,一般要手工实验很多次才会出现一次,哪位有没有碰到过这种问题,有什么好的建议没有? 以前记得有人发现过这个问题,好像是个bug,你搜索一下论坛找找。 析构的时的崩溃时发生的哪个线程?
主线程还是工作线程?
印象里ACE_Log_Msg是一个线程一个实例。
贴一些更为详细的信息出来,比如堆栈,线程等 感觉可能被双删除引起的BUG,我以前也遇到过类似的问题。
在多线程调用下,引用计数器可能会出现判断错误。
你开了一个10个线程的线程池,是否可以尝试在svc里面增加一个ACE_Recursive_Thread_Mutex锁,即
ACE_Recursive_Thread_Mutex m_ThreadWriteLock
m_ThreadWriteLock.acquire();
。。。//这里是你的ACE_Log_Msg操作
m_ThreadWriteLock.release(); 析构的时候,错误显示的是工作线程,准确说最后一个工作线程析构的时候。这个问题比较难重现,出现概率不等。最近在ACE Bug列表中看到ACE_TSS好像存在问题,不知道是否是这个问题引起的,ACE TSS的bug见http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=3539。 感觉可能被双删除引起的BUG,我以前也遇到过类似的问题。
在多线程调用下,引用计数器可能会出现判断错误。 ...
freeeyes 发表于 2010-7-21 10:01 http://www.acejoy.com/bbs/images/common/back.gif
LOG MSG对象写入文件的时候,会自动调用加锁操作。 前几天看仔细看过 Singleton模式线程安全的实现,貌似ACE Double-Check Singleton也未必是线程安全的,很多问题也可能是这些地方导致的,只是举个例子。 前几天看仔细看过 Singleton模式线程安全的实现,貌似ACE Double-Check Singleton也未必是线程安全的,很多问题也可能是这些地方导致的,只是举个例子。
页:
[1]