Microsoft provides a complete service sample to start with writing Windows services. However, I do not understand the following part from this file :
ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );
// TO_DO: Perform work until service stops.
while(1)
{
// Check whether to stop the service.
WaitForSingleObject(ghSvcStopEvent, INFINITE);
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}
I don't understand the point of the infinite loop containing a return statement. Doesn't it defeat the purpose ?
It seems to encourage to write the service content before the while loop but then, if we do not reach the following line :
WaitForSingleObject(ghSvcStopEvent, INFINITE);
... The service will not able to stop when the proper event is triggered, would it ?
Is this template flawed ? How can I make my service wait for an external trigger without making it impervious to stop calls ?
Yes, that example is not particularly well-written. The main loop of the service is better written (conceptually) as:
// Main processing loop
while (!quit)
do_work ();
ReportSvcStatus (SERVICE_STOPPED, NO_ERROR, 0);
return;
And in the service's control handler, you would have:
// CtrlHandler callback
DWORD WINAPI CtrlHandler (DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
...
if (dwControl == SERVICE_CONTROL_STOP)
quit = true;
return NO_ERROR;
}
Where quit is a global variable.
In practise (to avoid busy looping), the service probably normally sits around waiting on some sort of waitable object for something to do. Let's imagine, for the sake of argument, that's a HANDLE called, say, ghWakeupEvent, created via CreateEvent(), and again stored in a global variable.
Then, the code becomes something like:
// Main processing loop
while (1)
{
WaitForSingleObject (ghWakeupEvent, INFINITE);
if (quit)
{
ReportSvcStatus (SERVICE_STOPPED, NO_ERROR, 0);
return;
}
if (something_to_do)
do_work ();
}
// CtrlHandler callback
DWORD WINAPI CtrlHandler (DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
...
if (dwControl == SERVICE_CONTROL_STOP)
{
quit = true; // do this first!!
SetEvent (ghWakeupEvent);
}
return NO_ERROR;
}
Note: no need for (or point in) ghSvcStopEvent. The MSDN sample is a mixed-up mess.
Related
Hi i'm testing dll hijacking scenario for the educational purpose and i have problem when DllMain loaded i want to create something that keeps my method (Thread) running but the problem is even if i create a new thread still when DllMain reaches at the end my thread killed with it !
if i do something like WaitForSingleObject or while (1) {} it causes the deadlock of course
Also i want to prevent the Main Process (executable file) to exit ! because when the applications loads all modules after that it close him self ! and that's not what i want ! i want to keep the application running . as long as the application is running my thread is live
any thoughts or advise ?
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)LiveBackgroundListenerFunction, 0, 0, 0);
}
//while (1) {} #DeadLock !!!
//WaitForSingleObject(hdl, 100); #DeadLock !!!
return TRUE;
void LiveBackgroundListenerFunction()
{
While(1)
{
Sleep(5000);
//Do Somthing......
}
}
thanks in advance
I used to unload an injected library by calling FreeLibraryAndExitThread from a thread that was created using CreateThread.
The need to unload the library from a different thread rendered this approach impossible. Now I'm using TerminateThread (as it doesn't terminate the thread it's called from, but the one that is passed) and FreeLibrary separately. However as the WinAPI docs suggest this creates a "race condition" and crashes the process. Is there any way to fix this?
Old code:
HMODULE g_hModule{ NULL };
BOOL WINAPI DllMain(HMODULE hModule, DWORD fwdReason, LPVOID lpReserved) {
g_hModule = hModule;
if (fwdReason == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(hModule);
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)main, 0, 0, 0);
}
return TRUE;
}
void Unload(int nExitCode) {
FreeLibraryAndExitThread(g_hModule, (DWORD)nExitCode);
}
New code:
HMODULE g_hModule{ NULL };
HANDLE g_hThread{ NULL };
BOOL WINAPI DllMain(HMODULE hModule, DWORD fwdReason, LPVOID lpReserved) {
g_hModule = hModule;
if (fwdReason == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls(hModule);
g_hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)main, 0, 0, 0);
}
return TRUE;
}
void Unload(int nExitCode) {
TerminateThread(g_hThread, (DWORD)nExitCode);
FreeLibrary(g_hModule);
}
Thanks in advance for any help!
The only way to terminate a thread safely, in C++ especially, is to have that thread return from the function passed to CreateThread. This is usually done by setting (say) an atomic<bool> that the thread tests regularly to see if it should exit. You might also use a condition variable (or the Win32 equivalent) to wake the thread up, rather than busy-looping.
TerminateThread is deadly dangerous as, for example, the thread might be holding some kind of critical lock (perhaps the one used by malloc) at the time and that would hang the rest of your app. It should never have been provided in the Win32 API in the first place and you should not use it.
I'm getting a crash sometimes in RegisterWaitForSingleObject (1 out of 10). It seems that although RegisterWaitForSingleObject returns, the internal thread pool is not yet ready.
HANDLE processHandle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, processID);
// CRASH IN INTERNAL SOMETIMES
RegisterWaitForSingleObject (&hWaitForChild_,processHandle,OnChildProcessExit, 0,INFINITE,WT_EXECUTEONLYONCE);
// If I sleep here, then it seems ok.
//std::this_thread::sleep_for (std::chrono::milliseconds (10));
CloseHandle (processHandle);
I can replicate this with a simple sample here. 1 in 10 times, it will crash. How should I be synchronizing it properly without resorting to sleep hack.
https://filedn.com/l3TGy7Y83c247u0RDYa9fkp/temp/stackoverflow/testregister.cpp
based on your code spinet:
// THIS CRASHS HERE SOMETIMES
if (! RegisterWaitForSingleObject (
&hWaitForChild_
,processHandle
, OnChildProcessExit
, 0 //this
, INFINITE
, WT_EXECUTEONLYONCE))
{
LogDebug ("RegisterWaitForSingleObject failed");
}
// If this is enabled, then it won't crash
//std::this_thread::sleep_for (std::chrono::milliseconds (10));
if (! CloseHandle (processHandle)) // !!!
LogDebug ("RegisterWaitForSingleObject Closehandle failed");
so you close processHandle just after you call RegisterWaitForSingleObject for this handle. however if read about RegisterWaitForSingleObject:
If this handle is closed while the wait is still pending, the
function's behavior is undefined.
if look more deep - try understand - how is RegisterWaitForSingleObject worked internally ? it pass processHandle to some worker thread. and this thread begin wait for this handle. but this is (pass handle to another thread) is asynchronous operation - say for example internally can be started new thread with this handle as argument, or it can be passed to already existing working thread via some signal. but anyway - worked thread got this handle and begin wait some later. from another side - you just close processHandle after RegisterWaitForSingleObject return control. so here race - what will be first - or worked thread begin wait on handle (in this case all will be work) or you close this handle. in case you close this handle first - worked thread will be try wait on already invalid handle and raise exception - STATUS_THREADPOOL_HANDLE_EXCEPTION.
// If this is enabled, then it won't crash
//std::this_thread::sleep_for (std::chrono::milliseconds (10));
of course - by sleep you give time for worked thread to begin wait on handle. in this case he begin wait before you close handle.
solution - you must not close handle, until WAITORTIMERCALLBACK Callback will be not called. you need allocate some context, where place processHandle and pass this context to RegisterWaitForSingleObject. and when you callback will be called - you got pointer to your context back and here and close handle.
also note, that you not need open separate, second, handle for child process, but can use process handle returned by CreateProcess
Ok, I managed to solve it by keeping the handle around until I call Unregisterwait. It seems to be stable. Thanks to the answers.
I met the same problem like you that an exception occurred while debugging in Visual Studio. I tried many time and finally found the reason. If you close the handle of the process newly created, the program would crash. I tried to close the handles in the callback function, it works perfectly, like this:
typedef struct {
LPTSTR pszCmdLine;
HANDLE hEvent;
} THREAD_PARAM;
typedef struct {
TCHAR szCmdLine[1024];
HANDLE hWaitObject;
DWORD dwProcessId;
HANDLE hProcess;
DWORD dwThreadId;
HANDLE hThread;
} OBJECT_PARAM;
static void CALLBACK WaitObjectCallback(LPVOID lpParam, BOOLEAN TimerOrWaitFired)
{
OBJECT_PARAM *pobp = static_cast<OBJECT_PARAM *>(lpParam);
TCHAR szInfo[1024] = { 0 };
DWORD dwExitCode = 0;
GetExitCodeProcess(pobp->hProcess, &dwExitCode);
wnsprintf(szInfo, ARRAYSIZE(szInfo), _T("process %u [%s] exit: %u\n"), pobp->dwProcessId, pobp->szCmdLine, dwExitCode);
OutputDebugString(szInfo);
//
// unregister the wait object handle and close the process handle finally
//
UnregisterWait(pobp->hWaitObject);
CloseHandle(pobp->hProcess);
CloseHandle(pobp->hThread);
GlobalFree(lpParam);
}
static DWORD CALLBACK ThreadFunction(LPVOID lpParam)
{
THREAD_PARAM *pthp = static_cast<THREAD_PARAM *>(lpParam);
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
BOOL bResult;
bResult = CreateProcess(nullptr, pthp->pszCmdLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi);
if (bResult)
{
OBJECT_PARAM *pobp = static_cast<OBJECT_PARAM *>(GlobalAlloc(GPTR, sizeof(OBJECT_PARAM)));
// make copy of the command line and other informations of the newly created process
lstrcpyn(pobp->szCmdLine, pthp->pszCmdLine, ARRAYSIZE(pobp->szCmdLine));
pobp->dwProcessId = pi.dwProcessId;
pobp->hProcess = pi.hProcess;
pobp->dwThreadId = pi.dwThreadId;
pobp->hThread = pi.hThread;
bResult = RegisterWaitForSingleObject(&pobp->hWaitObject, pi.hProcess, WaitObjectCallback, pobp, INFINITE, WT_EXECUTEONLYONCE);
// once it failed...
if (!bResult)
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
// Notify the thread creator that the process is created successfully
SetEvent(pthp->hEvent);
return 0;
}
I've got to debug some code which is not from me.
This code implement a timer API using winapi Timer interface.
I'm not very used to this Winapi functionality, so i could use your help :)
From what I understand this code is done like this :
=> Init()
timerQueue = CreateTimerQueue();
=> CreateTimer()
CreateTimerQueueTimer(timerHandle, timerQueue, timerCallback, ..., WT_EXECUTEDEFAULT);
=> timerCallback()
DeleteTimerQueueTimer(timerQueue , timerHandle, NULL));
calback() //Launch user-defined callback
=> CleanUp() // to be called at the end
DeleteTimerQueueEx(timerQueue , INVALID_HANDLE_VALUE);
When we test that, user-defined callback are executed successfully after the desired amount of time. But after that timerCallback threads keep pending and never return, preventing the all process to returns. Using VS debugger I can see those threads (named TppWorkerThread#4) on the thread...
Perhaps we miss something to make callback returns properly or we created some sort of deadlocks... However I cannot figure it out ...
Please let me know if I forgot some relevant information.
Thank you for your help.
EDIT:
Further information :
- Blocking thread are at this state at the end of the process :
* Category :Worker Thread
* Name : _TppWorkerThread#4
* Location : _ZwWaitForWorkViaWorkerFactory#8
* Priotity : Normal
EDIT2:
Having some more time to work on that strange behavior, I am now able to reproduce it in a standalone code.
#include <windows.h>
#include <stdio.h>
HANDLE gDoneEvent;
HANDLE hTimer[5];
HANDLE hTimerQueue = NULL;
HANDLE g_threadHandle;
void PeriodicCallback(void)
{
printf("Periodic routine called.\n");
}
void SingleCallback(void)
{
printf("Single routine called.\n");
if (!DeleteTimerQueueTimer(hTimerQueue, hTimer[2], NULL))
printf("DeleteTimerQueueTimer() fail. Return value is %d.\n", GetLastError());
}
void CALLBACK CommonCallback(PVOID lpParam, BOOLEAN TimerOrWaitFired)
{
printf("Common routine called. Parameter is %d.\n", *(int *)lpParam);
((void (*)(void))lpParam)();
}
void MainTest(void)
{
// Use an event object to track the TimerRoutine execution
gDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == gDoneEvent)
{
printf("CreateEvent failed (%d)\n", GetLastError());
return -1;
}
if(0 == SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL))
{
printf("SetThreadPriority failed (%d)\n", GetLastError());
return -2;
}
// Create the timer queue.
hTimerQueue = CreateTimerQueue();
if (NULL == hTimerQueue)
{
printf("CreateTimerQueue failed (%d)\n", GetLastError());
return -3;
}
/*
if (!CreateTimerQueueTimer( &hTimer[2], hTimerQueue,
(WAITORTIMERCALLBACK)CommonCallback, &SingleCallback, 1000, 0, WT_EXECUTEDEFAULT))
{
printf("CreateTimerQueueTimer failed (%d)\n", GetLastError());
return -4;
}
*/
if (!CreateTimerQueueTimer( &hTimer[4], hTimerQueue,
(WAITORTIMERCALLBACK)CommonCallback, &PeriodicCallback, 10, 500, WT_EXECUTEDEFAULT))
{
printf("CreateTimerQueueTimer failed (%d)\n", GetLastError());
return -5;
}
// TODO: Do other useful work here
printf("Call timer routine in 10 seconds...\n");
Sleep(4000);
CloseHandle(gDoneEvent);
if (!DeleteTimerQueueTimer(hTimerQueue, hTimer[4], INVALID_HANDLE_VALUE))
printf("DeleteTimerQueueTimer failed (%d)\n", GetLastError());
// Delete all timers in the timer queue.
if (!DeleteTimerQueueEx(hTimerQueue, INVALID_HANDLE_VALUE))
printf("DeleteTimerQueue failed (%d)\n", GetLastError());
Sleep(1000);
ExitThread(0);
}
int main(int argc, char **argv[])
{
if(g_threadHandle == CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MainTest, NULL, 0, NULL))
printf("Creation fail");
ExitThread(0);
}
I'm compiling this code on VisualStudio 2010 Professional.
It appears that event after calling DeleteTimerQueueTimer() some threads remain pending on the threads pool, preventing my process to shutdown. I still cannot figured it out ...
When you call DeleteTimerQueueEx with an INVALID_HANDLE_VALUE as its second parameter it will block until all callbacks which are running have completed. The Error may be in one of your callback functions which never returns.
You are calling DeleteTimerQueueTimer(timerQueue , timerHandle, NULL); with NULL as the third parameter, this will not wait for the callback to complete if one is running at the time you delete the timer. I suggest using DeleteTimerQueueTimer(timerQueue , timerHandle, INVALID_HANDLE_VALUE) which will block until the call back completes (if one is running). Calling cleanUp() without using the blocking version of DeleteTimerQueueTimer is likely a bug as you may be cleaning up at the same time as the callback is executing.
It could also be a problem of calling DeleteTimerQueueEx or DeleteTimerQueueTimer from within a callback, which is forbidden. Break on execution of DeleteTimerQueueEx and look at what thread you are in, if its a TppWorkerThread than you have found your bug.
EDIT:
In your comment you say you do call DeleteTimerQueueTimer from within the callback but don't use INVALID_HANDLE_VALUE, reading the documentation again from http://msdn.microsoft.com/en-us/library/windows/desktop/ms682569%28v=vs.85%29.aspx this does seem to be legal but I distinctly remember us making design decisions to avoid this, I'm sorry this is so vague, I hope someone can give authoritative advice on this.
We send an event/message to the queue of a non timer thread which then removes the timer, you could even have a dedicated thread for this but that is probably overkill. At the end of the day you need to be sure that the timer is removed before doing cleanup so you have to either block on removal or have some other thread do it upon signaling of an event.
After some work on that issue I think I got to an answer.
I appears that this timerQueue API is coded on top of threadPool winAPI, and when we ask to create a timerQueue Windows create a thread pool from where all callback will be launched.
Until here no problem, but, when we ask for timerQueue deletion, it appears that this thread pool is not deleted...
This result in some thread keeping pending waiting to be used and preventing the process to returns.
After some time (timeout??) those threads returns and the process exit.
I don't really get why this pool is not closed... but, now, I use a workaround :
exit(0);
At the end of my program, it's a bit brutal but it does the job (ie: killing my process, whatever threads are still pending or not)
I have a dialog. in this dialog ::OnInitDialog() I create a thread AfxBeginThread((AFX_THREADPROC)MyThreadProc, NULL); It crashes when I close the dialog with run time check failure, and it is pointing to thrdcore.cpp file (Microsoft Foundation Classes C++ library)
// first -- check for simple worker thread
DWORD nResult = 0;
if (pThread->m_pfnThreadProc != NULL)
{
nResult = (*pThread->m_pfnThreadProc)(pThread->m_pThreadParams);
ASSERT_VALID(pThread);
}
I have a code to kill the thread OnClose function, but it doesn't solve the issue. Can some help, what I am missing? My code for
HANDLE m_hExit;
DWORD dwResult = 0;
unsigned threadID = 0;
...
OnInitDialog()
{...
m_hExit = (HANDLE)AfxBeginThread((AFX_THREADPROC)MyThreadProc, NULL);
}
OnClose()
{
dwResult = WaitForSingleObject(m_hExit, 0);
if (dwResult == WAIT_TIMEOUT)
{
printf("The thread is still running...\n");
}
else
{
printf("The thread is no longer running...\n");
}
Sleep(10000);
dwResult = WaitForSingleObject(m_hExit, 0);
if (dwResult == WAIT_TIMEOUT)
{
printf("The thread is still running...\n");
}
else
{
printf("The thread is no longer running...\n");
}
CDialog::OnClose();
}
thread function is very big((((
AfxBeginThread is documented as requiring the threadproc to be
UINT __cdecl MyControllingFunction( LPVOID pParam );
Your comment says your function is
UINT WINAPI MyThreadProc( LPVOID pParam )
WINAPI is defined as _stdcall (see here)
So you have a mismatch of calling conventions. As others already commented, the cast is suspicious. In fact, that's the only reason your code is compiling. If you remove the cast, the compiler should show an error.
The solution is to remove the cast and then fix the calling convention of your function. Once that code compiles correctly without the cast, it should run properly without corrupting the stack.