How can you get the return value of a Windows thread? - c++

I was just wondering if it is possible (and if so, how) to get the return value of a thread in C++ (Windows). I have several threads, and I use WaitForMultipleObjects(...) on them. This waits until a thread is done, and returns the index of said thread, and all is well. However, I want to be able to obtain the return value of the thread that finished using its handle.
For example:
DWORD WINAPI Thread1(void *parameter){
...
if(...) return 0;
else return -1;
}
DWORD WINAPI Thread2(void *parameter){
...
if(...) return 1;
else return 0;
}
int main(){
HANDLE t1 = CreateThread(0, 0, Thread1, NULL, 0, 0);
HANDLE t2 = CreateThread(0, 0, Thread2, NULL, 0, 0);
HANDLE *threads = new HANDLE[2];
threads[0] = t1;
threads[1] = t2;
int result = WaitForMultipleObjects(2, threads, false, INFINITE);
if(result == 0){
//get the threads value here:
int retVal = SomeFunction(t1); //What is SomeFunction?
}
...
}
I have tried to use GetExitCodeThread(thread) but I'm assuming this returns a system exit code, as it always gives me a very strange integer. Does anyone know a way, or a workaround?

GetExitCodeThread is the correct function. Here is the MSDN description of what it does:
This function returns immediately. If the specified thread has not
terminated and the function succeeds, the status returned is
STILL_ACTIVE. If the thread has terminated and the function succeeds,
the status returned is one of the following values:
The exit value specified in the ExitThread or TerminateThread function.
The return value from the thread function.
The exit value of the thread's process.

The problem with most programmer is that they don't pay attention to compiler warnings. At level 4 (/W4), the compiler produces following warning when returning -1 from a function that is returning DWORD:
warning C4245: 'return' : conversion from 'int' to 'DWORD', signed/unsigned mismatch

you need to check for STILL_ACTIVE for the values one of these threads may still be active

You can use C++ 11's threads concepts using std::future.
See an example below.
int ReturnFrmThread() {
return 100;
}
int main() {
std::future<int> GetRetVal= std::async(ReturnFrmThread); // Execution of ReturnFrmThread starts
int answer = GetAnAnswer.get(); // gets value as 100;
// Waits until ReturnFrmThread has finished
}

Related

How to pass function pointer as lpParameter to CreateThread?

I have the following function which will be called by CreateThread:
DWORD WINAPI start_thread(LPVOID handleFunction)
{
int prio = 4;
// call handleFunction()
handleFunction(prio);
return TRUE;
}
And I create the thread here:
DECL_PREFIX tid_t so_fork(so_handler *handleFunction, unsigned priority) {
DWORD dw;
hThr[currentThread] = CreateThread(
NULL, // default security attributes
0, // use default stack size
(LPTHREAD_START_ROUTINE)start_thread, // thread function name
(LPVOID)&handleFunction, // argument to thread function
0, // use default creation flags
&dw); // returns the thread identifier
return 0;
}
I get the following error when I am builind it:
Error C2064 term does not evaluate to a function taking 1 arguments libscheduler
expression preceding parentheses of apparent call must have (pointer-to-) function type libscheduler
What am I doing it wrong?
Passing &handleFunction to CreateThread() is wrong, because you are passing the local address of the handleFunction variable itself, not the address of the so_handler that it is pointing at.
Since handleFunction is already a pointer, try something more like this instead:
DWORD WINAPI start_thread(LPVOID handleFunction)
{
int prio = 4;
// call handleFunction()
so_handler *handler = (so_handler *) handleFunction;
handler(prio); // or maybe (*handler)(prio), depending on how so_handler is actually defined...
return TRUE;
}
DECL_PREFIX tid_t so_fork(so_handler *handleFunction, unsigned priority) {
DWORD dw;
hThr[currentThread] = CreateThread(
NULL, // default security attributes
0, // use default stack size
&start_thread, // thread function name
handleFunction, // argument to thread function
0, // use default creation flags
&dw); // returns the thread identifier
return 0;
}

The handle OpenThread() had returned,QueueUserApc() thinks it is invalid

I would to use the function--QueueUserApc(),but it returns 0,and GetLastError() returns 6--invalid handle.There is only one handle--the second parameter of the function QueueUserApc(),but it was returned by OpenThread().so what's wrong there??????
part of the code:
void WINAPI My_IDtoHandle(IN PDWORD IDArray,
IN DWORD dwNumber,
OUT PHANDLE * Thread_Handle_Array)
{
PHANDLE handlearray;
DWORD count = 0;
handlearray = (PHANDLE)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwNumber*sizeof(HANDLE));
for (; count < dwNumber; count++)
{
handlearray[count] = OpenThread(THREAD_ALL_ACCESS,
FALSE,
IDArray[count]);
if (handlearray[count] == NULL)
printf("Open the thread-%d is failed!\n\n", IDArray[count]);
}
*Thread_Handle_Array = handlearray;
return;
}
call the function above:
result = QueueUserAPC((PAPCFUNC)SetEvent,
Thread_Handle_Array[count],
(ULONG_PTR)(Target_Event_Handle_Array + count));
if (result == 0)
{
printf("The inserting of the %dth function-SetEvent is failed!\n\n", count + 1);
printf("The error code is %d\n\n", GetLastError());
}
And the handle the OpenThread returned is strang:
It seems that the problem was attempting to queue an APC to a 64-bit thread from a 32-bit thread.
The documentation says:
Similarly, if a 64-bit process queues an APC to a 32-bit process or vice versa, addresses will be incorrect and the target application will crash.
... which was apparently added in response to a bug report as described in this USENET post seven years ago. At that time it seems that any such call to QueueUserAPC() would fail with ERROR_INVALID_FUNCTION but would also crash the target thread.
It seems likely that this issue was later addressed by explicitly blocking any such attempt and reporting ERROR_INVALID_HANDLE.

How to check if WriteFile function is done

I want to check if the WriteFile function is done writing to UART so that i can call ReadFile on the same ComDev without causing an Exception.
It seems the WriteFile function can return before writing is done.
BOOL WriteCommBlock(HANDLE * pComDev, char *pBuffer , int BytesToWrite)
{
while(fComPortInUse){}
fComPortInUse = 1;
BOOL bWriteStat = 0;
DWORD BytesWritten = 0;
COMSTAT ComStat = {0};
OVERLAPPED osWrite = {0,0,0};
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{
short Errorcode = GetLastError();
if( Errorcode != ERROR_IO_PENDING )
short breakpoint = 5; // Error
Sleep(1000); // complete write operation TBD
fComPortInUse = 0;
return (FALSE);
}
fComPortInUse = 0;
return (TRUE);
}
I used Sleep(1000) as an workaround, but how can i wait for an appropriate time?
You can create a Event, store it in your overlapped structure and wait for it to be signalled. Like this (untested):
BOOL WriteCommBlock(HANDLE * pComDev, char *pBuffer , int BytesToWrite)
{
while(fComPortInUse){}
fComPortInUse = 1;
BOOL bWriteStat = 0;
DWORD BytesWritten = 0;
COMSTAT ComStat = {0};
OVERLAPPED osWrite = {0,0,0};
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hEvent != NULL)
{
osWrite.hEvent = hEvent;
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{
short Errorcode = GetLastError();
if( Errorcode != ERROR_IO_PENDING )
short breakpoint = 5; // Error
WaitForSingleObject(hEvent, INFINITE);
fComPortInUse = 0;
return (FALSE);
}
CloseHandle(hEvent);
}
fComPortInUse = 0;
return (TRUE);
}
Note that depending on what else you are trying to do simply calling WaitForSingleObject() might not be the best idea. And neither might an INFINITE timeout.
Your problem is the incorrect use of the overlapped I/O, regardless to the UART or whatever underlying device.
The easiest (though not necessarily the most optimal) way to fix your code is to use an event to handle the I/O completion.
// ...
OVERLAPPED osWrite = {0,0,0};
osWrite.hEvent = CreateEvent(FALSE, NULL, NULL, FALSE);
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{
DWORD Errorcode = GetLastError();
// ensure it's ERROR_IO_PENDING
WaitForSingleObject(osWrite.hEvent, INFINITE);
}
CloseHandle(osWrite.hEvent);
Note however that the whole I/O is synchronous. It's handles by the OS in an asynchronous way, however your code doesn't go on until it's finished. If so, why do you use the overlapped I/O anyway?
One should use it to enable simultaneous processing of several I/Os (and other tasks) within the same thread. To do this correctly - you should allocate the OVERLAPPED structure on heap and use one of the available completion mechanisms: event, APC, completion port or etc. Your program flow logic should also be changed.
Since you didn't say that you need asynchronous I/O, you should try synchronous. It's easier. I think if you just pass a null pointer for the OVERLAPPED arg you get synchronous, blocking, I/O. Please see the example code I wrote in the "Windows C" section of this document:
http://www.pololu.com/docs/0J40/
Your Sleep(1000); is of no use, it will only execute after the writefile completes its operation.You have to wait till WriteFile is over.
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{}
You must be knowing that anything inside conditionals will only execute if the result is true.
And here the result is sent to the program after completion(whether complete or with error) of WriteFile routine.
OK, I missed the overlapped I/O OVL parameter in the read/write code, so It's just as well I only replied yesterday as a comment else I would be hammered with downvotes:(
The classic way of handling overlapped I/O is to have an _OVL struct as a data member of the buffer class that is issued in the overlapped read/write call. This makes it easy to have read and write calls loaded in at the same time, (or indeed, multiple read/write calls with separate buffer instances).
For COM posrts, I usually use an APC completion routine whose address is passed in the readFileEx/writeFileEx APIs. This leaves the hEvent field of the _OVL free to use to hold the instance pointer of the buffer so it's easy to cast it back inside the completion routine, (this means that each buffer class instance contains an _OVL memebr that contains an hEvent field that points to the buffer class instance - sounds a but weird, but works fine).

COM port read - Thread remains alive after timeout occurs

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.

How to terminate a hanging thread inside a dll correctly?

Hi Everybody,
I have a third party library that contains an error. When I call a function it may hang. The library function is called inside a dll. I decided to move the call into the thread and wait for some time. If thread is finished then OK. If not – I should terminate it compulsory.
The simplified example here:
unsigned Counter = 0;
void f()
{
HANDLE hThread;
unsigned threadID;
// Create the second thread.
hThread = (HANDLE)_beginthreadex( NULL, 0, DoSomething, NULL, 0, &threadID );
if (WAIT_TIMEOUT == WaitForSingleObject( hThread, 5000 ))
{
TerminateThread(hThread, 1);
wcout << L"Process is Timed Out";
}
else
{
wcout << L"Process is Ended OK";
}
CloseHandle(hThread);
wcout << Counter;
}
unsigned int _stdcall DoSomething( void * /*dummy*/ )
{
while (1)
{
++Counter;
}
_endthreadex( 0 );
return 0;
}
The Question
The TerminateThread() function is not recommended to call.
As I mentioned before, the thread is running inside a dll. If I terminate the thread using TerminateThread() my dll would not unload using FreeLibrary() or even FreeLibraryAndExitThread(). Both functions hangs.
How to Terminate the thread and keep FreeLibrary() working?
Thanks.
Unfortunately, you can't arbitrarily terminate a thread safely.
TerminateThread causes the thread to terminate immediately, even if the thread is holding locks or modifying some internal state. TerminateThread can cause random hangs in your application (if the thread was holding a lock) or a crash (if the thread were modifying some state and it is left inconsistent)
If you cannot trust the DLL to behave correctly and this is causing significant reliability issues for you, you should move the code invoking the DLL into a separate process - terminating a process is much safer.