注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

gmd20的个人空间

// 编程和生活

 
 
 

日志

 
 

我发现我越来越聪明了^_^  

2008-10-06 19:18:20|  分类: 程序设计 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

又解决了语音聊天程序中的一个死锁问题,原因是用到了jrtplib库中的 BeginDataAccess 和EndDataAccess函数时,在这两个函数之间调用RTPSession类的Destroy ()函数销毁对象之后,EndDataAccess函数没能正确释放互斥锁。所以等到下次调用RTPSession类的create重新创建时,这个互斥锁就死锁了,因为还有其他几个线程也在请求这个互斥锁,就会死锁忙等待了。


void RTPClient::Stop(void)
{
int a=1,b =1;
a= BeginDataAccess(); //返问数据时,需要锁定数据,同步
{
// 注意,BeginDataAccess ()要放在CAutoLock lck(& _csData); 一句的前面
//,不然和OnPollThreadStep() -》ProcessRTPPacket ()里面的顺序不一样,就会出现两个锁互相请求的死锁情况
     ASSERT(CritCheckOut(& _csData)); // This assert will fire.

    CAutoLock lck(& _csData); //锁定 _data和 _endPosition 等
RTPPacket * packet ;
while (packet= _data.RemoveHead ())
{
         DeletePacket(packet);
}
     this->_endPosition =0;
this->_startPosition =0;

}
b= EndDataAccess();
ASSERT(a==b && b==0);
//ERR_RTP_SESSION_NOTCREATED
//如果先调用 BYEDestroy () 然后再 调用EndDataAccess () ,就会出现EndDataAccess 函数
//返回值是ERR_RTP_SESSION_NOTCREATED 的情况,但BeginDataAcces 已经锁定了资源访问的mutext互斥锁了,
//EndDataAccess 出错实际没有释放掉锁,所以等下次再重新 “启动” 其他线程就会等待这个锁了,死锁就出现了。
//所以this->BYEDestroy(RTPTime(10,0),0,0);   一句不能放在BeginDataAccess 和EndDataAccess 之间
// BeginDataAccess 和EndDataAccess 函数都返回0 才能确保互斥锁被正确的lock和unlock

this->BYEDestroy(RTPTime(10,0),0,0);

    WSACleanup();
}

=============================

跟踪时中断后,发现两个线程停在JMutex::lock()函数上,这是jrtplib多线程库中的类。所以为了调试方便,我修改了这个类,模拟directshow中

//用于跟踪调试锁, 结合//DbgInitialise(hInstance); //DbgTerminate(); 来使用
//DbgSetModuleLevel(LOG_LOCKING,3);
// DbgLockTrace (& _csData, TRUE);//监控_csData 的状况

等几个用于调试锁状态的函数,加上了打印调试信息的语句,然后运行,检查调试输出,终于发现问题所在,如上面所说。

修改后的类如下,红色部分为我自己添加的打印调试信息的。

/*

    This file is a part of the JThread package, which contains some object-
    oriented thread wrappers for different thread implementations.

    Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com)

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.

*/
#ifdef _DEBUG
   #include <stdio.h>
#endif

#include "jmutex.h"

JMutex::JMutex()
{
initialized = false;
}

JMutex::~JMutex()
{
if (initialized)
#ifdef JMUTEX_CRITICALSECTION
   DeleteCriticalSection(&mutex);
#else
   CloseHandle(mutex);
#endif // JMUTEX_CRITICALSECTION
}

int JMutex::Init()
{
if (initialized)
   return ERR_JMUTEX_ALREADYINIT;
#ifdef JMUTEX_CRITICALSECTION
InitializeCriticalSection(&mutex);
#else
mutex = CreateMutex(NULL,FALSE,NULL);
if (mutex == NULL)
   return ERR_JMUTEX_CANTCREATEMUTEX;
#endif // JMUTEX_CRITICALSECTION
initialized = true;
return 0;
}

int JMutex::Lock()
{
if (!initialized)
   return ERR_JMUTEX_NOTINIT;
#ifdef JMUTEX_CRITICALSECTION
EnterCriticalSection(&mutex);
#else
WaitForSingleObject(mutex,INFINITE);
#endif // JMUTEX_CRITICALSECTION

#ifdef _DEBUG
char debugOutput[256];
    sprintf(debugOutput,"Thread %d now owns lock 0x%04x\n", GetCurrentThreadId(),(void*)mutex);
    OutputDebugString(debugOutput);
#endif

   
return 0;
}

int JMutex::Unlock()
{
if (!initialized)
   return ERR_JMUTEX_NOTINIT;
#ifdef JMUTEX_CRITICALSECTION
LeaveCriticalSection(&mutex);
#else
ReleaseMutex(mutex);
#endif // JMUTEX_CRITICALSECTION
#ifdef _DEBUG

char debugOutput[256];
    sprintf(debugOutput,"Thread %d releasing lock 0x%04x\n", GetCurrentThreadId(),(void*)mutex);
    OutputDebugString(debugOutput);
#endif

return 0;
}

  评论这张
 
阅读(591)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017