2009-11-06 4 views
9

스레드가 DllMain에서 DLL_PROCESS_ATTACH에 생성 될 때 모든 dll이로드 될 때까지 시작되지 않는 것 같습니다. 계속하기 전에 스레드가 실행되는지 확인해야하므로 교착 상태가 발생합니다. 스레드를 시작하도록 강제 할 수있는 방법이 있습니까?DllMain에서 스레드 만들기?

답변

10

당신은 특히 DLLMain에서 스레드 또는 창을 만들 같은 것들에 대한 모든 API 호출을 수행 할 수 없습니다. 레이몬드 첸 (Raymond Chen)은 이것에 대해 여러 번 기록했다. 특히 관련이있는 one입니다.

+10

CreateThread는 이미로드 된 것으로 보장되는 kernel32를 호출하기 때문에 DllMain에서 수행 할 수있는 몇 가지 작업 중 하나입니다. –

+2

@Ben Voigt 현재 DllMain 호출에 새로운 스레드로부터의 반환을 기다리는 경우 데드 록을 얻는 것이 쉽기 때문에 매우 조심해야합니다. – mloskot

+0

@ mloskot :'DllMain'에서 대기 함수를 호출하는 것은 당신이 기다리고있는 객체의 종류에 상관없이 매우 나쁩니다. 일반적으로 DLL에서 코드를 실행하는 모든 스레드는 해당 DLL에 대한 참조 카운트가 있어야하며 코드가 그 아래에서 매핑되지 않습니다. 스레드가 실행되는 동안'DllMain'은 (프로세스 분리를 ​​위해) 호출되지 않기 때문에 문제가 발생하지 않습니다. –

5

아니요. DllMain에서 CreateThread (또는 임의의 변경)를 호출하면 안됩니다. 동기화를 시도하면 교착 상태가 _ 생합니다. 너 정확히 뭘 하려구?

Best Practices for Creating DLLs

+7

CreateThread를 호출해도 아무런 문제가 없지만 부모 스레드에서 DllMain 처리가 완료 될 때까지 스레드가 일시 중단된다는 사실을 알 수 없습니다. –

0

이렇게하면 문제가 발생합니다. dll (C 라이브러리 호출 등) 외부에있는 함수에는 직접 또는 간접적으로 호출하지 않아야합니다.

DLL을 변경할 수없는 경우 (예 : 소스 코드가없는 경우) 은 DLL이 나머지 종속 DLL이 모두로드 된 후에 동적으로로드되는 경우이 문제를 해결할 수 있습니다. 초기화 됨. 종속성 체인을 알아내는 것이 항상 사소한 것은 아니기 때문에 (예 : dll이 종속 DLL로 하여금 COM 또는 일부 다른 방법을 통해 동적으로 세 번째로드 할 경우)이 방법을 사용하지 않는 것이 좋습니다.

+2

첫 번째 단락은 지나친 일반화입니다. 사실 전에 DLL이로드되기 전에 호출 된 DLL을 호출하는 것은 완벽합니다. 일반적으로 그리고 대부분의 상황에서 이것은 KERNEL32.DLL만을 의미하며, 이는 막대한 한계처럼 들릴 수 있지만,이 상황에서 부트 스트랩하기 위해 사용할 수 있습니다. –

+2

http://blogs.msdn.com/oldnewthing/archive/2007/09/04/4731478.aspx –

+0

감사 정수 시인. 이것으로 제가 풀기 위해 온 질문과 정확하게 일치합니다. –

5

스레드의 기능은 무엇입니까?

DllMain에서 수행 할 수있는 작업에 대한 제한을 피하기 위해 두 번째 스레드로 물건을 이동하려는 경우 힘든 행운이 있습니다. DllMain이 수행 할 수있는 작업에는 제한이 없으며 DllMain이 실행되는 동안 수행 할 수있는 작업에 대한 제한이 있습니다 (로더 잠금을 보유하고 있음). 스레드가 로더 잠금을 받아야하는 경우 첫 번째 스레드가 로더 잠금을 사용할 때까지 기다립니다. 스레드가 로더 잠금을 필요로하지 않는 경우 왜 즉시 계속할 수 없는지 알 수 없지만 로더 잠금을 필요로하지 않는 스레드는 없습니다. 스레드가 실행을 시작하기 전에 Windows가 DLL_THREAD_ATTACH 메시지를 모든 DLL로 보내야합니다. 즉, DLL 자체가 DllMain이라고도 부르며 Windows는 재입국을 방지합니다.

이 문제를 해결할 방법이 없습니다. DLL_THREAD_ATTACH 처리가 끝날 때까지 스레드를 시작할 수 없으며 첫 번째 스레드가 DllMain 안에있는 동안 스레드를 실행할 수 없습니다. 이 문제를 해결할 수있는 유일한 방법은 새 프로세스를 시작하는 것입니다.이 프로세스는 독립적 인 로더 잠금을 가지고 있으며 사용자의 대기를 차단하지 않습니다.

+0

'DLL_PROCESS_ATTACH' 메시지를 처리하는 동안'DLLMain()'에서 매우 간단한 작업자 함수로'CreateThread()'를 사용하는 간단한 시도를했습니다. 쓰레드 함수는 1000 밀리 초 동안'Sleep()'을 사용했다. 모든 것이 잘 작동했습니다. DLL_THREAD_ATTACH 메시지와 DLL_THREAD_DETACH 메시지는 DLL_PROCESS_ATTACH를 수행하는 초기 스레드와 첨부 처리 중에 생성 된 스레드 모두에서 볼 수 있습니다. 그러나이 작업자 스레드는'Sleep()'이외에 아무것도하지 않았습니다. Kernel32.dll 호출은 정상적으로 처리되어야합니다. VS 2005 Windows 7에서 테스트되었습니다. –

+0

이상하게도이 질문은 질문 된 문제를 해결하는 유일한 대답입니다. 나는 왜 OP가 대답을 받아들이기로 결정했는지 모른다. – IInspectable

관련 문제