출처: http://kslive.tistory.com/15

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에 스레드나 프로세스 생성같은 코드를 넣지 않겠다. 꽝꽝꽝!

AND