The following simple code doesn't operate as I expected. It creates a thread (suspended), starts it, waits for it to run for 1 millisecond and loops waiting until the thread dies or fails.
I expected the output to be something along the lines of:
Start
Callback running
Callback running
Callback running
WaitForSingleObject looping
Callback running
Callback running
WaitForSingleObject looping
Callback running
Callback running
WaitForSingleObject looping
Callback running
Callback running
... repeating for 10000 times
End
Thread end
But the output is:
Start
Callback running
Callback running
Callback running
Callback running
Callback running
... repeating for 10000 times
Callback running
End
WaitForSingleObject looping
Thread end
I thought that the wait in WaitForSingleObject would timeout at some point and interrupt the thread at some point? But the thread seems to be blocking and not asynchronous?
DWORD WINAPI callback(LPVOID param)
{
printf("Start\n");
for (int i=10000; i>0; i--)
printf("Callback running\n");
printf("End\n");
return 1;
}
int main()
{
HANDLE hThread = CreateThread(NULL, 0, callback, 0, CREATE_SUSPENDED, 0);
if (!hThread) {
printf("Failed to create thread\n");
return 0;
}
ResumeThread(hThread);
while (WaitForSingleObject(hThread, 1) == WAIT_TIMEOUT) {
printf("WaitForSingleObject looping\n");
}
CloseHandle(hThread);
printf("Thread end\n");
system("PAUSE");
return 0;
}
The dwMilliseconds parameter in WaitForSingleObject cannot be relied upon for accurate timing. The only contract is that after that much time has elapsed, the thread will eventually wake up and return the TIMEOUT value. The thread may not wake up until its next scheduled quanta, which can be as high as 60 milliseconds (or even higher on Windows Server). This is more than enough time for the second thread to complete. Try increasing the iteration count such that the worker thread takes at least one second to run - that should be plenty of time for the primary thread to be scheduled and run at least one more iteration of the TIMEOUT loop.
Related
I have a multithreaded C++ Windows application. The worker thread is an infinite loop waiting for events to process, one of which is a kill thread event from main thread. The problem is that sometimes it takes a really long time (think seconds) for the worker thread to receive the kill event and terminate. Other times it's very quick (milliseconds).
// Main thread code
void deactivate()
{
while (isWorkerThreadRunning)
{
// Problem: sometimes it spends a long time in this loop
logDebug("deactivate: killing worker thread");
SetEvent(killWorker);
Sleep(20);
}
}
// Worker thread code
DWORD WINAPI WorkerThreadProc(LPVOID arglist)
{
isWorkerThreadRunning = true;
logDebug("Worker thread started");
for (bool done = false; done != true; )
{
HANDLE handles[3] = { killWorker, action1, action2 };
DWORD rc = WaitForMultipleObjects(3, handles, FALSE, INFINITE);
switch (rc)
{
case WAIT_OBJECT_0 + 0: done = true; break;
case WAIT_OBJECT_0 + 1: doAction1(); break;
case WAIT_OBJECT_0 + 2: doAction2(); break;
default: logWarn("Unhandled wait signal");
}
}
isWorkerThreadRunning = false;
logDebug("Worker thread killed");
return 0;
}
I believe that if the worker thread receives a kill event while it is busy inside doAction1() or doAction2() the kill event won't be received and processed until doAction1() or doAction2() is completed and returned. And if doAction1() or doAction2() takes a long time to return then the worker thread will take a long time to exit.
However, I have log points sprinkled throughout doAction1() and doAction2() but I don't see any of those log points in the log file. All I see are:
deactivate: killing worker thread
deactivate: killing worker thread
deactivate: killing worker thread
deactivate: killing worker thread
//....many more times
Worker thead killed
which means the worker thread is not doing any work but rather waiting inside the WaitForMultipleObjects() call.
The question is why is the WaitForMultipleObjects() call sometimes take a long time (and sometimes very quick) to signal the waiter of an event??
Would changing the timeout from INFINITE to some reasonable number fix this problem?
Thanks,
Your declaration of isWorkerThreadRunning should be volatile if it is not. You can get some strange behavior when the compiler optimizes the code if it is not volatile.
volatile bool isWorkerThreadRunning;
I would also suggest entry and exit messages in your doAction functions. That will make it clearer if you're still inside one of those functions when the exit signal is sent.
I have a parent process and I'd like to spawn the child process for a certain duration ( say N milli seconds). I'm doing this in c++ (and windows).
Can I provide some parameter to CreateProcess that would kill it after a while and return control to the parent application ? If not, is there any other way to do this ?
Can I provide some parameter to CreateProcess...?
Yes, you may pass the desired duration (N) with the parameter lpCommandLine to the process to be started.
The child process may parse lpCommandLine and set up a timer with the desired
duration. This timer could for example be a Waitable Timer or simply a thread with
Sleep(duration); // waits the duration
ExitProcess(GetLastError()); // exits the "remote" process
The thread (a thread inside the the child process) terminates the entire child process after duration. The WaitableTimer idea would need a frequent call to a wait function. See Using Waitable Timer Objects for details.
But: The parent process will remain "in control" all the time.
However: You may additionally
enter a wait state in the parent process, using a wait function (e.g. WaitForSingleObject, waiting on the child processes handle to actually hibernate the parent process until the child process terminates. On top you may evaluate the return value of the child process by a call to the GetExitCodeProcess function.
The described schemes ensures that the desired duration is best performed, however, you may also control the duration from the parent process by means of a named event. See Using Event Objects for details. In such an approach, the parent process may set an event when the duration "is consumed". The child process waits for that event and terminates when the event was set. This approach may be a little less accurate since the parent doesn't quite know when the childs duration started.
Example with waitable timer:
Parent process:
...
#define CHILD_DURATION 2000 // 2000 ms
HANDLE hProcess;
char ChildName[MAX_PATH];
char CommandLine[MAX_PATH];
sprintf_s(ChildName,MAX_PATH,"MyChild.exe");
sprintf_s(CommandLine,MAX_PATH,"%d",CHILD_DURATION);
// start the child
hProcess = CreateProcess(ChildProcessName,CommandLine,....
if (0 == hProcess)
{
// error with process creation
printf("CreateProcessfailed (%d)\n", GetLastError());
return GetLastError();
}
// and wait for it to finish
if (WAIT_OBJECT_0 == WaitForSingleObject(hProcess,INFINITE)
{
// child finished
} else
{
// error with wait
printf("WaitForSingleObject failed (%d)\n", GetLastError());
return GetLastError();
}
...
Child process:
int main(int argc, char * argv[])
{
HANDLE hWaitableTimer CreateWaitableTimer(NULL,TRUE,NULL);
if (NULL == hWaitableTimer)
{
printf("CreateWaitableTimer failed (%d)\n", GetLastError());
return GetLastError();
}
DWORD dwDuration = atoi(argv[1]);
LARGE_INTEGER liDueTime = -10000 * dwDuration;
// waitable timer due time is in 100 nano second units
// negative values indicate relative time
if (!SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0))
{
printf("SetWaitableTimer failed (%d)\n", GetLastError());
return GetLastError();
}
DWORD dwKeepGoing = TRUE;
// enter the "to do" loop while waiting for the timer...
While (dwKeepGoing)
{
switch (WaitForSingleObject(hTimer,0)
{
case WAIT_OBJECT_0:
// duration over,
// optionally finalize "to do" stuff here
// and end child
dwKeepGoing = FALSE;
case WAIT_TIMEOUT:
// do stuff here
break;
case WAIT_FAILED:
// the wait function has failed
printf("WaitForSingleObject failed (%d)\n", GetLastError());
return GetLastError();
}
}
return 0;
}
Noone will kill the process for you, unless you either do it on your own (e.g. from parent process), or the process exits itself.
Note that there is also no such thing as "and return control to the parent application". Once child process is started, both parent and child processes have their own "control" and run simultaneously, consuming CPU time given to the processes by the operating system.
All in all, you decide who will be terminating the process. If you do it from parent process, then once started you keep child process handle and use (not a good idea though) TerminateProcess API toward the child process.
Otherwise, and this is the better one, the child process itself keep looking at runtime and just exits when it's time to do so:
main() {
time_to_exit = now() + N;
while(now() < time_to_exit) {
keep_doing_my_stuff();
}
}
I have a dll which includes a function called ReadPort that reads data from serial COM port, written in c/c++. This function is called within an extra thread from another WINAPI function using the _beginthreadex. When COM port has data to be read, the worker thread returns the data, ends normaly, the calling thread closes the worker's thread handle and the dll works fine.
However, if ReadPort is called without data pending on the COM port, when timeout occurs then WaitForSingleObject returns WAIT_TIMEOUT but the worker thread never ends. As a result, virtual memory grows at about 1 MB every time, physical memory grows some KBs and the application that calls the dll becomes unstable. I also tryied to use TerminateThread() but i got the same results.
I have to admit that although i have enough developing experience, i am not familiar with c/c++. I did a lot of research before posting but unfortunately i didn't manage to solve my problem.
Does anyone have a clue on how could i solve this problem? However, I really want to stick to this kind of solution. Also, i want to mention that i think i can't use any global variables to use some kind of extra events, because each dll's functions may be called many times for every COM port.
I post some parts of my code below:
The Worker Thread:
unsigned int __stdcall ReadPort(void* readstr){
DWORD dwError; int rres;DWORD dwCommModemStatus, dwBytesTransferred;
int ret;
char szBuff[64] = "";
ReadParams* params = (ReadParams*)readstr;
ret = SetCommMask(params->param2, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD | EV_RING);
if (ret == 0)
{
_endthreadex(0);
return -1;
}
ret = WaitCommEvent(params->param2, &dwCommModemStatus, 0);
if (ret == 0)
{
_endthreadex(0);
return -2;
}
ret = SetCommMask(params->param2, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD| EV_RING);
if (ret == 0)
{
_endthreadex(0);
return -3;
}
if (dwCommModemStatus & EV_RXCHAR||dwCommModemStatus & EV_RLSD)
{
rres = ReadFile(params->param2, szBuff, 64, &dwBytesTransferred,NULL);
if (rres == 0)
{
switch (dwError = GetLastError())
{
case ERROR_HANDLE_EOF:
_endthreadex(0);
return -4;
}
_endthreadex(0);
return -5;
}
else
{
strcpy(params->param1,szBuff);
_endthreadex(0);
return 0;
}
}
else
{
_endthreadex(0);
return 0;
}
_endthreadex(0);
return 0;}
The Calling Thread:
int WINAPI StartReadThread(HANDLE porthandle, HWND windowhandle){
HANDLE hThread;
unsigned threadID;
ReadParams readstr;
DWORD ret, ret2;
readstr.param2 = porthandle;
hThread = (HANDLE)_beginthreadex( NULL, 0, ReadPort, &readstr, 0, &threadID );
ret = WaitForSingleObject(hThread, 500);
if (ret == WAIT_OBJECT_0)
{
CloseHandle(hThread);
if (readstr.param1 != NULL)
// Send message to GUI
return 0;
}
else if (ret == WAIT_TIMEOUT)
{
ret2 = CloseHandle(hThread);
return -1;
}
else
{
ret2 = CloseHandle(hThread);
if (ret2 == 0)
return -2;
}}
Thank you in advance,
Sna.
Don't use WaitCommEvent. You can call ReadFile even when there is no data waiting.
Use SetCommTimeouts to make ReadFile itself timeout, instead of building a timeout on the inter-thread communications.
Change the delay in the WaitForSingleObject call to 5000 or 10000 and I bet your problem frequency goes way down.
Edwin's answer is also valid. The spawned thread does not die because you closed the thread handle.
There is no guarantee that the ReadPort thread has even started by the time you are timing out. Windows takes a LONG time to start a thread.
Here are some suggestions:
You never check the return value of beginthreadex. How do you know the thread started?
Use whatever synchronization method with which you are comfortable to sync the ReadPort thread startup with StartReadThread. It could be as simple as an integer flag that ReadPort sets to 1 when its ready to work. Then the main thread can start its true waiting at that point. Otherwise you'll never know short of using a debugger what's happening between the 2 threads. Do not time out from the call to WaitForSingleObject in StartReadThread until your sync method indicates that ReadPort is working.
You should not use strcpy to copy the bytes received from the serial port with ReadFile. ReadFile tells you how many bytes it read. Use that value and memcpy to fill the buffer.
Look here and here for info on how to have ReadFile time out so your reads are not indefinite. Blocking forever on Windows is a recipe for disaster as it can cause zombie processes you cannot kill, among other problems.
You communicate no status to StartReadThread about what happened in the ReadPort thread. How do you know how many bytes ReadPort placed into szBuff? To get the theads exit code, use GetExitCodeThread. Documented here. Note that you cannot use GetExitCodeThread if you've closed the thread handle.
In your calling thread after a timeout you close the threadhandle. This will only stop you from using the handle. The worker thread however is still running. You should use a loop which waits again.
Im trying to implement out of process rendering for my application (like what chrome does). I have the ipc (interprocess communication) all set up and working however it just deadlocks when trying to init a new form on the other process.
I have started the process with inherit handles as true is there any thing else i need to do?
I happy to provide sample code if needed.
Edit: it deadlocks in window api calls. Runs fine when in the same process
It is very easy to couple two threads if they own windows with any kind of relationship.
The effective result of this is, your IPC calls cannot block when waiting for a reply - your IPC reads always need to use MsgWaitForMultipleObjects so that you can process window messages from the other process/thread while waiting for the IPC message indicating completion.
What you do is replace your current call to WaitForMultipleObjects with MSGWaitForMultipleObjects. When it returns, you check the return value. If nCount is the number of IPC handles you are waiting to be signalled:
// Pump messages while waiting on 0 or more handles.
for(;;)
{
while(PeekMessage(&msg,0,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
DWORD ret = MsgWaitForMultipleObjects(nCount,pHandles,FALSE,dwTimeout,QS_ALLEVENTS);
if(ret >= WAIT_OBJECT_0 && ret < (WAIT_OBJECT_0 + nCount))
{
// one of the handles was signalled.
return ret;
}
else if(ret == WAIT_OBJECT_0 + nCount)
{
// The wait was aborted because there is at least one message,
// go back to pumping messages
continue;
}
else
{
// test for WAIT_OBJECT_ABANDONED_0, WAIT_TIMEOUT etc. as appropriate
}
}
I spawn a thread using AfxBeginThread which is just an infinite while loop:
UINT CMyClass::ThreadProc( LPVOID param )
{
while (TRUE)
{
// do stuff
}
return 1;
}
How do I kill off this thread in my class destructor?
I think something like
UINT CMyClass::ThreadProc( LPVOID param )
{
while (m_bKillThread)
{
// do stuff
}
return 1;
}
and then set m_bKillThread to FALSE in the destructor. But I still need to wait in the destructor until the thread is dead.
Actively killing the thread:
Use the return value of AfxBeginThread (CWinThread*) to get the thread handle (m_hThread) then pass that handle to the TerminateThread Win32 API. This is not a safe way to terminate threads though, so please read on.
Waiting for the thread to finish:
Use the return value of AfxBeginThread (CWinThread*) to get the member m_hThread, then use WaitForSingleObject(p->m_hThread, INFINITE); If this function returns WAIT_OBJECT_0, then the thread is finished. Instead of INFINITE you could also put the number of milliseconds to wait before a timeout happens. In this case WAIT_TIMEOUT will be returned.
Signaling to your thread that it should end:
Before doing the WaitForSingleObject just set some kind of flag that the thread should exit. Then in your main loop of the thread you would check for that bool value and break the infinite loop. In your destructor you would set this flag then do a WaitForSingleObject.
Even better ways:
If you need even more control you can use something like boost conditions.
BTW, About TerminateThread(), use it this way.
DWORD exit_code= NULL;
if (thread != NULL)
{
GetExitCodeThread(thread->m_hThread, &exit_code);
if(exit_code == STILL_ACTIVE)
{
::TerminateThread(thread->m_hThread, 0);
CloseHandle(thread->m_hThread);
}
thread->m_hThread = NULL;
thread = NULL;
}
First you have to start the thread in a way so MFC doesn't delete the thread object when it's finished, the default setting for MFC thread is to delete itself so you want to turn that off.
m_thread = AfxBeginThread(ThreadProc, this, THREAD_PRIORITY_NORMAL ,CREATE_SUSPENDED);
m_thread->m_bAutoDelete = FALSE;
m_thread->ResumeThread();
Now in the thread, you want a mechanism that the caller thread can send it a signal to end itself. There are multiple ways, one is the WaitForSingleObject to check the status of the signal or another way is to simply send this thread a message to end itself. This is graceful ending rather killing it.
While this thread is ending itself (= exiting the thread function, cleaning up), you can have the main thread wait on it to finish before it exits.
int wait = 2000 // seconds ( I am waiting for 2 seconds for worker to finish)
int dwRes = WaitForSingleObject( m_thread->m_hThread, wait);
switch (dwRes)
{
case WAIT_OBJECT_0:
TRACE( _T("worker thread just finished") ); break;
case WAIT_TIMEOUT:
TRACE( _T("timed out, worker thread is still busy") ); break;
}
Note setting m_bAutoDelete = FALSE above made it possible we still have a valid handle when thread finishes so we can wait on it. The last thing you want to do now is delete the CWinThread object to free its memory (since we took the responsibility to do that).
You must wait, until thread do all stuff.
if(WaitForSingleObject(thread_handle, INFINITE) == WAIT_OBJECT_0)
;//all right
else
;//report error
beware using TerminateThread function, this is very dangerous.