Jun 24, 2010 at 3:49pm UTC
Hello everybody,
I am working with a thread for implementing a timer. If the thread is started / exited directly from an application (standard exe) everything works fine, but if I create and exit it from within a DLL loaded by the application, WaitForSingleObject fails to detect the thread exit. Why is that?
WaitForSingleObject exits with WAIT_TIMEOUT after 5 seconds instead of WAIT_OBJECT_0 (the one that I expect) and then I am forced to kill the thread with
TerminateThread.
I used the scroll key LED and Dbgview (OutputDebugString) for debugging.
In case someone were so kind to help me I could send a sample C++ builder project with the code below (including a testing console for loading / unloading the DLL library).
Anyone can help?
Thank you very much in advance!!!!!!
Here is the code:
#include <windows.h>
#include <stdio.h>
HANDLE MyThreadHandle = NULL;
DWORD MyThreadId = 0;
bool MyThreadEnable = false;
void DebugMess(char *sMess)
{
char sDbg[257];
sprintf(sDbg, "PID=%04x,TID=%04x: %s", GetCurrentProcessId(), GetCurrentThreadId(), sMess);
OutputDebugString(sDbg);
}
DWORD WINAPI ThreadFunction(void *unused)
{
DebugMess("Thread loop enter");
while (MyThreadEnable)
{
DebugMess("Thread running...");
keybd_event(VK_SCROLL, 0, 0, 0);
Sleep(500);
keybd_event(VK_SCROLL, 0, KEYEVENTF_KEYUP, 0);
Sleep(500);
}
DebugMess("Thread loop exit");
return 0;
}
void ThreadCreate(void)
{
SECURITY_ATTRIBUTES saAttr;
if (MyThreadHandle == NULL)
{
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = true;
saAttr.lpSecurityDescriptor = NULL;
MyThreadHandle = CreateThread (
&saAttr ,
0 ,
ThreadFunction ,
(LPVOID) NULL ,
CREATE_SUSPENDED ,
&MyThreadId );
if (MyThreadHandle != NULL)
{
MyThreadEnable = true;
}
}
return;
}
void ThreadDestroy(void)
{
if (MyThreadHandle)
{
/* Exit from loop */
MyThreadEnable = false;
/* Wait thread exit */
switch (WaitForSingleObject(MyThreadHandle, 1000))
{
case WAIT_OBJECT_0 :
{
DebugMess("Thread ended OK");
break;
}
case WAIT_TIMEOUT :
{
DebugMess("WaitForSingleObject - timeout");
TerminateThread(MyThreadHandle, 0);
break;
}
default :
{
DebugMess("WaitForSingleObject - other");
TerminateThread(MyThreadHandle, 0);
break;
}
}
keybd_event(VK_SCROLL, 0, KEYEVENTF_KEYUP, 0);
CloseHandle(MyThreadHandle);
MyThreadHandle = NULL;
MyThreadId = 0;
}
}
void _DllTimerProcessAttach(void)
{
DebugMess("Attaching process...");
ThreadCreate();
if (MyThreadHandle)
{
ResumeThread(MyThreadHandle);
}
else
{
DebugMess("Thread creation failed");
}
}
void _DllTimerProcessDetach(void)
{
DebugMess("Detaching process...");
ThreadDestroy();
}
void _DllTimerThreadAttach(void)
{
DebugMess("Attaching thread...");
}
void _DllTimerThreadDetach(void)
{
DebugMess("Detaching thread...");
}
And the DllEntryPoint function:
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
int iDllProcess;
switch ( reason )
{
case DLL_THREAD_ATTACH :
{
_DllTimerThreadAttach();
iDllProcess = 1;
break;
}
case DLL_THREAD_DETACH :
{
_DllTimerThreadDetach();
iDllProcess = 1;
break;
}
case DLL_PROCESS_ATTACH :
{
_DllTimerProcessAttach();
iDllProcess = 1;
break;
}
case DLL_PROCESS_DETACH :
{
_DllTimerProcessDetach();
iDllProcess = 1;
break;
}
}
return ( iDllProcess );
}
and the log file:
00000000 0.00000000 [3996] PID=0f9c,TID=0ff4: Attaching process...
00000001 0.00010768 [3996] PID=0f9c,TID=0ff8: Attaching thread...
00000002 0.00017417 [3996] PID=0f9c,TID=0ff8: Thread loop enter
00000003 0.00022960 [3996] PID=0f9c,TID=0ff8: Thread running...
00000004 0.99959105 [3996] PID=0f9c,TID=0ff8: Thread running...
00000005 1.99953830 [3996] PID=0f9c,TID=0ff8: Thread running...
00000006 2.99953294 [3996] PID=0f9c,TID=0ff8: Thread running...
00000007 3.99991632 [3996] PID=0f9c,TID=0ff8: Thread running...
00000008 4.99960756 [3996] PID=0f9c,TID=0ff8: Thread running...
00000009 5.99944973 [3996] PID=0f9c,TID=0ff8: Thread running...
00000010 6.99947405 [3996] PID=0f9c,TID=0ff8: Thread running...
00000011 7.73600912 [3996] PID=0f9c,TID=0ff4: Detaching process...
00000012 7.99939489 [3996] PID=0f9c,TID=0ff8: Thread loop exit
00000013 12.73392105 [3996] PID=0f9c,TID=0ff4: WaitForSingleObject - timeout
If I make a DLL function for closing the thread (which calls ThreadDestroy) instead of doing that at process detach (with FreeLibrary), it works, but I would like not to have to call a specific uninitialize function and do everything just with FreeLibrary.