DllMain이 실행되는 시기는 언제인가?


————————————————————————————


DLL_PROCESS_ATTACH  : 프로세스에 Dll이 최초 로드되는 경우에 호출된다.


DLL_PROCESS_DETACH  : Dll이 프로세스 주소공간에서 해제되는 경우에 호출된다.


DLL_THREAD_ATTACH    : 스레드가 생성이 되었을경우 현 프로세스 주소 공간에 존재하는 


                                                 모든 Dll들의 DllMain이 호출된다.


DLL_THREAD_DETACH    : 스레드가 종료되는 경우 현 프로세스 주소 공간에 존재하는


                                                 모든 Dll들의 DllMain이 호출된다.


————————————————————————————


이 와 같은 경우에 DllMain이 호출되며 여기서 눈을 여겨 보아야할 부분은  DllMain 함수의


실행방법이다.


다음과 같은 경우가 있다.


switch(pArg)


{


case DLL_PROCESS_ATTACH:


           {


                         HANDLE aThread = CreateThread(. . . . . .);


                         WaitSignleObject(aThread, INFINITE);


                         CloseHandle(aThread);


           }


           break;
}


이 Dll은 프로세스에 최초 로드시 스레드를 하나 생성하며 이 스레드이 핸들이 시그널될때까지 대기 후 해당 스레드의 핸들을 닫는다.


겉으로 보기에는 아무 문제도 없는 코드다.


하지만 DllMain의 동작을 아는 사람이 보면 이 Dll은 교착상태를 100% 유발하는 코드라고 볼수있다. 어느 부분에서 교착상태(Dead-lock)이 발생할까?


1. Dll이 최초 로드가 되어 프로세스 주소 공간에 자리를 잡으며 DllMain을 호출한다.


2. DllMain에서 DLL_PROCESS_ATTACH: 이 부분이 실행이 되며 스레드를 생성한다.


3. 스레드를 생성하였으므로 DllMain을 다시 호출한다.(DLL_THREAD_ATTACH)


자 어느 부분일까? 문제는 2번과 3번의 사이에서 발생을 한다.


하나의 DllMain은 동시에 하나에 스레드에서 진입 및 실행이 가능하다. 이 말인즉 하나의 DllMain을 두 스레드 이상에서 호출하였을경우 하나의 스레드씩 순서대로 입장하여 해당 DllMain이 리턴을 할때 까지 다른 스레드들은 대기상태로 존재한다는 것이다.


그럼 위의 코드가 어디에서 교착상태가 발생하는지는 말하지않아도 알수있지 않을까?


그렇다 주스레드의 WaitForSingleObject(… , INFINITE) 와 생성된 스레드의 DllMain진입과정에서 일어난다.


주스레드는 생성된 스레드의 핸들이 시그널 될때까지 대기한다.(DllMain을 붙잡고 있는상태)


생성된 스레드는 DllMain을 실행하고 나서야 스레드가 시작되기때문에 DllMain에 진입할려는 상태로 존재하는것이다.


Dll을 제작시 이 부분을 유의하자. 나는 앞으로 DllMain에 스레드나 프로세스 생성같은 코드를 넣지 않겠다. 꽝꽝꽝!

Post to Twitter