解决Windows Dll入口函数中Wait系函数死锁的解决


layout: post
title: 解决Windows Dll入口函数中Wait系函数死锁的解决
categories: Windows
description: 解决Windows Dll入口函数中Wait系函数死锁的解决
keywords:
url: https://lichao890427.github.io/ https://github.com/lichao890427/


案例

  dll中如果用了等待系函数会形成死锁,《Windows核心编程》给出了一个例子

//***exe.cpp
LoadLibrary(***dll.cpp);

//***dll.cpp
DWORD __stdcall func(LPVOID)
{
    Sleep(2000);
    cout<<"in thread"<<endl;
    return 0;
}
BOOL WINAPI DllMain(HINSTANCE hInstDll,DWORD fdwReason,PVOID fImpLoad)
{
    if(fdwReason == DLL_PROCESS_ATTACH)
    {
        HANDLE hthread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)func,NULL,0,NULL);
        if(hthread)
            WaitForSingleObject(hthread);//这里会死锁
    }
    else if(fdwReason == DLL_THREAD_ATTACH)
    {

    }
}

分析

  这是一个很常见的错误,死锁原因是这样的:在loadlibrary之后,系统加载器执行到dllmain之前,会调用EnterCriticalSection锁住进程的“加载器锁”,而dllmain中的wait函数会共用这个“加载器锁”,再次锁住该锁,因此造成死锁,,,正常的情况是:waitForsingleobject之前就执行完dllmain,之后系统加载器执行LeaveCriticalSection,之后再去wait就不会发生死锁,而现在的情况是,wait在等dllmain执行完,而dllmain在等wait执行完。dllmain中不能用wait系函数也是出自这个原因,如果读了内核代码,会更明白这一块。核心编程的作者说,他能想到的解决办法只有在dllmain中不要出现wait系函数,这种是不良设计思路。事实上MSDN上也说不推荐dllmain中存在耗时操作,所以他们才这么设计的!因为加载dll本身就是很复杂的,很费时间片的工作!!!,核心编程的作者尝试DisableThreadLibraryCall来破解限制,然而没成功。

解决

  这里我提出2种方式来破解锁限制,且都可以成功,第一种比较暴力,直接leave掉加载器锁,wait之后再恢复即可,代码如下:

if(reason == DLL_PROCESS_ATTACH)
{
    cout<<"inside dll!"<<endl;
    PCRITICAL_SECTION loaderlock=NULL;
    _asm
    {
        mov eax,fs:[0x18];
        mov eax,[eax+0x30];
        mov eax,[eax+0xa0];
        mov loaderlock,eax;
    }
    LeaveCriticalSection(loaderlock);
    HANDLE hthread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)func,NULL,0,NULL);
    if(hthread)
    {
        cout<<"create succeed!"<<endl;
    }
    WaitForSingleObject(hthread,INFINITE);
    EnterCriticalSection(loaderlock);
}
else if(reason == DLL_THREAD_ATTACH)
{
    cout<<" DLL_THREAD_ATTACH"<<endl;
}

return 0;

  这种做法的缺点是,无法保证可重入性,但如果dll足够简单的话,也不妨一试,第二种则采用事件等待的方法,比较规矩:

void main()
{
    HANDLE hEvent=CreateEventA(NULL,TRUE,FALSE,"Initial");
    HMODULE hmod=LoadLibraryA("C:\\Users\\Administrator\\Documents\\Visual Studio 2010\\Projects\\test1\\Debug\\testdl.dll");
    WaitForSingleObject(hEvent,INFINITE);
    CloseHandle(hEvent);
    cout<<"Success!!"<<endl;
}

DWORD __stdcall func(LPVOID)
{
    cout<<"in thread"<<endl;
    HANDLE hEvent=OpenEventA(EVENT_ALL_ACCESS,TRUE,"Initial");
    if(hEvent)
    {
        SetEvent(hEvent);
        CloseHandle(hEvent);
    }
    return 0;
}

int __stdcall DllMain(int,int reason,int)
{
    if(reason == DLL_PROCESS_ATTACH)
    {
        cout<<"inside dll!"<<endl;
        CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)func,NULL,0,NULL);
    }
    else if(reason == DLL_THREAD_ATTACH)
    {
        cout<<" DLL_THREAD_ATTACH"<<endl;
    }
    return TRUE;
}

  为防止滥用,再次强调一下,在dllmain中最好不要放置耗时操作。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容