Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows C++ - closing thread with CloseHandle

Tags:

c++

windows

I have created a thread by the "CreateThread" function.

in this thread, I have a 'while(true)' loop (that reads input).

for now, when I want to close the thread, I use the 'CloseHandle' function.

Is this the right thing to do? Or I should exit the 'while(true)' loop and then use the 'CloseHandle' function?

Thanks

like image 557
kakush Avatar asked Jun 27 '12 12:06

kakush


People also ask

What does CloseHandle do?

In general, CloseHandle invalidates the specified object handle, decrements the object's handle count, and performs object retention checks. After the last handle to an object is closed, the object is removed from the system.

How do you close a process handle?

Assuming we find our handle, what do we do with it? Fortunately, there is a trick we can use that allows closing a handle in another process: call DuplicateHandle again, but add the DUPLICATE_CLOSE_SOURCE to close the source handle. Then close our own copy, and that's it!

What is WriteProcessMemory?

WriteProcessMemory copies the data from the specified buffer in the current process to the address range of the specified process. Any process that has a handle with PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process to be written to can call the function.


3 Answers

CloseHandle() does not destroy, terminate or supspend the thread, it only destroys the handle itself (so then you don't have a handle to kill the thread or wait on it). The thread continues to work normally (I have utilised this in numerous cases), and the only way to stop it is either exit the thread function (ThreadProc()), or kill it.

like image 123
Constantine Georgiou Avatar answered Oct 13 '22 13:10

Constantine Georgiou


Generally this (calling TerminateThread) is a bad thing to do because a thread may allocate some resources (i.e., file descriptors) which will be unavailable until the whole process terminate. Even more, the CloseHandle does not stop the thread.

If you have some lengthy operation inside your thread, then at least use the

while(!ShouldExit)
{
     DoOneMoreIteration();
}

cycle. This way you can terminate the thread by setting ShouldExit to 1 (or 'true', if it is C++ and bool variable) and the call WaitForSingleObject on this thread's handle to ensure it has finished.

For eran's comment: The ShouldExit must be declared as 'volatile'.

If you're waiting for some input (a console I suppose), then you might use the non-blocking ("overlapped") I/O with standard input.

E.g., see this question: Checking Win32 file streams for available input

It would be something like

HANDLE h = GetStdHandle(STD_INPUT_HANDLE);

while(!ShouldExit) {
   if(WaitForSingleObject(h, FALSE, SomeTimeoutValue) == WAIT_OBJECT_0)
   {
      ... use std::cin - it has some input and won't block
   }
}

To make things better (avoid CPU overburn) use WaitForMultipleObjects and break outside the loop on some external event.

/// Global var
HANDLE SomeGlobalEvent;

/// ThreadProc():
HANDLE h[2];
h[0] = GetStdHandle(STD_INPUT_HANDLE);
h[1] = SomeGlobalEvent;

while(true) {
   DWORD which = WaitForMultipleObjects(2, h, FALSE, SomeTimeoutValue);
   if(which == WAIT_OBJECT_0)
   {
      ... use std::cin - it has some input and won't block
   } else
   if(which == WAIT_OBJECT_1)
   {
      // got the termination event
      break;
   }
}


/// "Main" thread:

SomeGlobalEvent = CreateEvent(NULL, false, false, NULL);

HANDLE hThread = _beginthread(ThreadProc, 4096, NULL);

 ....
 /// send termination signal
 SetEvent(SomeGlobalEvent);

 /// Wait for thread completion
 WaitForSingleObject(hThread);
like image 42
Viktor Latypov Avatar answered Oct 13 '22 12:10

Viktor Latypov


Best thing is to read the docs carefully. Win32 API is well documented.

from MSDN on CreateThread in the Remarks section it says

Thread execution begins at the function specified by the lpStartAddr parameter. If this function returns, the DWORD return value is used to terminate the thread in an implicit call to the ExitThread function. Use the GetExitCodeThread function to get the thread's return value.

Following on from that, you should let the thread entry function do its job and finish. I.e. exit the loop which would return the thread entry function.

like image 23
Indy9000 Avatar answered Oct 13 '22 14:10

Indy9000