I am writing a multi-threaded networked application, and I'm using a separate thread with a blocking socket to receive data asynchronously from the server.
When I need to shutdown the socket I use a function which checks if the receive thread is still running and if it is calls TerminateThread to end it as follows:
DWORD dwExitCode = 0;
if( GetExitCodeThread( theApp.m_hRecvThread, &dwExitCode ) && dwExitCode == STILL_ACTIVE )
TerminateThread( theApp.m_hRecvThread, 0 );
However, GetExitCodeThread returns FALSE, and when polling GetLastError() it returns 6 (ERROR_INVALID_HANDLE). Which suggests that I do not have the THREAD_QUERY_INFORMATION or THREAD_QUERY_LIMITED_INFORMATION access rights on the m_hRecvThread handle.
My m_hRecvThread handle is set when creating the thread like so:
m_hRecvThread = AfxBeginThread( RecvThread, hWndMainFrame );
This successfully creates the thread, and the thread is running fine and exhibiting expected functionality. The TerminateThread and GetExitCodeThread are being called from the same thread which created the Receive thread in the first place.
My understanding was that when using AfxBeginThread, the HANDLE returned had THREAD_ALL_ACCESS access rights, is this the case, and if so, why am I still getting ERROR_INVALID_HANDLE?
Thanks in advance!
The thread created using:
m_hRecvThread = AfxBeginThread( RecvThread, hWndMainFrame )
will return a pointer to winthread. But GetExitCodeThread() requires the handle to the thread for example, you can pass RecvThread->m_hThread, which will solve the issue
Related
I think it is essential to send a message to the camera per some minutes ,so I initialize my camera and send message to camera every once in a while in my main thread , and in the other thread I open the liveview to process my other jobs, but in the liveview thread , it wait time out when sending this message :
EdsSetPropertyData(theCamera, kEdsPropID_Evf_Mode, 0, sizeof(evfMode), &evfMode)
I never met this when all jobs handled in just one thread, I don't know why it happends like this , could someone help me ? Here is some of my code.
my main thread : (I don't send keepalive message in the thread,but also timeout when starting liveview !)
CanonCameraWrapper& wrapper = param->wrapper;
bool setup_ok = wrapper.setup(0);
if (!setup_ok)
{
wrapper.destroy();
}
wrapper.setDownloadPath("img");
pthread_t camera_thread;
pthread_create(&camera_thread, NULL, camera_thread_func, (void *)(param));
pthread_join(camera_thread, NULL);
the other thread
void * camera_thread_func(void * arg)
{
global_param* param = (global_param*)arg;
CanonCameraWrapper& wrapper = param->wrapper;
wrapper.beginLiveView();//**//it wait time out here!!!**
...
}
I believe there are two things you have to be aware of. One is this notice in the Canon SDK documentation:
When creating applications that run under Windows, a COM initialization is required for each thread in order to
access a camera from a thread other than the main thread.
To create a user thread and access the camera from that thread, be sure to execute CoInitializeEx( NULL,
COINIT_APARTMENTTHREADED ) at the start of the thread and CoUnInitialize() at the end.
Sample code is shown below. This is the same when controlling EdsVolumeRef or EdsDirectoryItemRef objects
from another thread, not just with EdsCameraRef
The other thing is: you cannot access (most of) the SDK at the same time. So if you are using multiple threads you have to be careful about this
I have an application, which has registered handle routine via SetConsoleCtrlHandler . Thing is on break signal I have to do some cleanup before exiting, and that is when problems begin. Because, other threads keeps on running and using some of the resources which should freed I got access violation during cleanup. I tried to save thread instances which are using these resources and stop them before calling cleanup routine, but this did not help. I constantly get ERROR_INVALID_HANDLE. I tried to get thread instance via DuplicateHandle also I tried to save only thread id and then get thread handle via OpenThread function. But still invalid handle error is displayed.
Also, when I enumerate all thread instance and trying to terminate them I get the same error. It seems to me like there are some "magic" around handle routine, which does not allow to terminate other threads from it.
Listing for enumerating all threads
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (h != INVALID_HANDLE_VALUE) {
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(h, &te)) {
do {
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
sizeof(te.th32OwnerProcessID)) {
HANDLE thread = OpenThread(THREAD_TERMINATE, FALSE, te.th32ThreadID);
if (TerminateThread(thread , NUM_SIG_ACTION_1) == 0)
{
// printf("terminate failed (%d)\n", GetLastError());
if( SuspendThread(thread ) == -1)
{
// printf("suspend failed (%d)\n", GetLastError());
}
}
}
te.dwSize = sizeof(te);
} while (Thread32Next(h, &te));
}
CloseHandle(h);
}
Listing for get thread via DuplicateHandle
//code in working thread
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &g_hWorkerThread ,
DUPLICATE_SAME_ACCESS, FALSE, DUPLICATE_SAME_ACCESS);
//code in handler routine
if (TerminateThread( g_hWorkerThread , NUM_SIG_ACTION_1 ) == 0)
{
printf("Terminate thread failed (%d)\n", GetLastError());
}
Listing for OpenThread
//code from worker thread
g_iWorkerThreadId = GetThreadId(GetCurrentThread());
//code in routine handler
HANDLE handle = OpenThread(THREAD_TERMINATE, FALSE, g_iWorkerThreadId);
if (TerminateThread( handle , NUM_SIG_ACTION_1 ) == 0)
{
printf("Terminate thread failed (%d)\n", GetLastError());
}
Is there anyway to force handle routine run in to current worker thread?
Any help will be appreciated.
Thanks on advance.
You're trying to do something yourself that the OS already does. Don't fight the system.
Let me suggest another way of working, that could simplify your code considerably.
When your main application thread gets the Ctrl signal, it wants to shut down the application.
You can have Windows do that for you, but you might leave resources in an undefined state, so that's why you want to shut down gracefully.
Likely, each thread already runs an event loop - that's the basic Windows applications paradigm. Upon the ctrl-signal, post events to your other threads and catch them in each thread's event loop. Add custom event code that will make them gracefully end themselves. You now only have to wait for all the thread handles to ensure all threads have ended.
Using TerminateThread is not a good idea, it is exactly the opposite of the graceful end of a thread.
How one can sure calling TerminateThread will free the resource that is in use?
Only killing a process guarantees freeing of kernel resources used by the process.
In my humble experiences, I didn't found any multi-thread program runs good and stably without the clear and explicit exit mechanism.
Each thread must have an exit condition, when exiting it must free the resources, and the main thread (or controlling thread) must trigger the exit conditions and wait until all the other thread are exit.
Background:
In my application written in C++, I create a worker thread which in turn creates two threads using CreateThread(). The two threads which worker thread creates, talk to WCF Service through a client which is implemented using Windows Web Services API which offers C/C++ application programming interface (API) for building SOAP based web services and clients to them. My application implements only the client using this API.
Problem:
The problem I'm facing is that all other threads exit gracefully, except the worker thread, as you can see yourself, in the image below that WorkerThreadProc uses no CPU cycles yet it doesn't exit. There are also few other threads running which are not created by me, but by the runtime.
The thread states are as follows (as reported by ProcessExplorer):
WorkerThreadProc is in Wait:WrUserRequest state.
wWinMainCRTStartup is in Wait:UserRequest state.
All TpCallbackIndependent are in Wait:WrQueue state.
What are they waiting for? What could be possible causes that I need to look into? Also, what is the difference between WrUserRequest and UserRequest? And what does WrQueue mean? I've absolutely no idea what is going on here.
Here is my WorkerThreadProc code. I've removed all the logging statements except the last one at the bottom of the function:
DWORD WINAPI WorkerThreadProc(PVOID pVoid)
{
//Initialize GDI+
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
Status status = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
if ( status != Status::Ok )
{
return 1;
}
GuiThreadData *pGuiData = (GuiThreadData*)pVoid;
auto patternIdRequestQueue= new PatternIdRequestQueue();
auto resultQueue = new ResultQueue();
auto patternManager = new PatternManager(patternIdRequestQueue);
LocalScheduler *pScheduler = new LocalScheduler(resultQueue, patternManager);
bool bInitializationDone = pScheduler->Initialize(pGuiData->m_lpCmdLine);
if ( !bInitializationDone )
{
return 0;
}
//PatternIdThread
PatternIdThread patternIdThread(patternIdRequestQueue);
DWORD dwPatternIdThreadId;
HANDLE hPatternIdThread = CreateThread(NULL, 0, PatternIdThreadProc, &patternIdThread, 0, &dwPatternIdThreadId);
ResultPersistence resultPersistence(resultQueue);
DWORD dwResultPersistenceThreadId;
HANDLE hResultPersistenceThread = CreateThread(NULL, 0, ResultPersistenceThreadProc, &resultPersistence, 0, &dwResultPersistenceThreadId);
pScheduler->ScheduleWork(pGuiData->m_hWnd, pGuiData->m_hInstance, ss.str());
pScheduler->WaitTillDone();
patternIdThread.Close();
resultPersistence.Close();
delete pScheduler;
//Uninitialize GDI+
GdiplusShutdown(gdiplusToken);
dwRet = WaitForSingleObject(hPatternIdThread, INFINITE);
CloseHandle(hPatternIdThread);
dwRet = WaitForSingleObject(hResultPersistenceThread,INFINITE);
CloseHandle(hResultPersistenceThread);
SendMessage(pGuiData->m_hWnd, WM_CLOSE, 0, 0);
//IMPORTANT : this verbose message is getting logged!
T_VERBOSE(EvtSrcInsightAnalysis, 0, 0, "After sending message to destroy window");
delete patternManager;
delete patternIdRequestQueue;
delete resultQueue;
return 0;
}
Please see the T_VERBOSE macro, it is used to log verbose message. I see the message is getting logged, yet the thread doesn't exit!
EDIT:
I just commented the following line in my WorkerThreadProc, then worker thread exits gracefully!
SendMessage(pGuiData->m_hWnd, WM_CLOSE, 0, 0);
Does it mean that SendMessage is the culprit? Why would it block the thread the calling thread?
If we look at the docs for SendMessage, you can see this little quote:
To send a message and return immediately, use the SendMessageCallback
or SendNotifyMessage function. To post a message to a thread's message
queue and return immediately, use the PostMessage or PostThreadMessage
function.
and this:
Messages sent between threads are processed only when the receiving
thread executes message retrieval code. The sending thread is blocked
until the receiving thread processes the message. However, the sending
thread will process incoming nonqueued messages while waiting for its
message to be processed. To prevent this, use SendMessageTimeout with
SMTO_BLOCK set. For more information on nonqueued messages, see
Nonqueued Messages.
so from this we can see SendMessage will block till the message is processed, which may somehow lead to a deadlock in your code, as the msgproc doesn't reside in your worker thread, leading to a context switch (which is only triggered when the thread's queue is pumped for messages). Try using PostMessage, which immediately returns.
EDIT: there is also a nice little piece of info here on message deadlocks from SendMessage
I'm creating 3 events with the following function:
HANDLE WINAPI CreateEvent(...);
I'm waiting on all (bWaitAll is set to TRUE) event objects or a timeout with:
DWORD WINAPI WaitForMultipleObjects(...);
The return value is:
WAIT_TIMEOUT
Is there an easy way to check each event to find the one(s) that was(where) not set?
As an example :
HANDLE evt1 = ....
HANDLE evt2 = ....
HANDLE evt3 = ....
HANDLE evts[3] = ....
DWORD ret = ::WaitForMultipleObjects(3, evts, TRUE, 10000);
After 10 sec :
'ret' is WAIT_TIMEOUT.
evt1 is set
evt2 is NOT set
evt3 is set
The return value tells me "The time-out interval elapsed and the conditions specified by the bWaitAll parameter are not satisfied.", but not which one were signaled and which one were not.
Thanks,
Yes, after WaitForMultipleObjects() returned call WaitForSingleObject() for each event specifying zero timeout.
It will return WAIT_TIMEOUT for events that are not signalled and WAIT_OBJECT_0 for signalled events. Don't forget to check for WAIT_FAILED.
Surely each event state might have been changed compared to the states they had at the moment WaitFormultipleObjects() returned.
OK. Total rewrite after having the question explained to me better in the comments.
So if I'm understanding this right now, you are calling WaitForMultipleObjects with bWaitAll set to true, and when you get WAIT_TIMEOUT back from it, want to figure out which objects are holding up the works.
In that case, I'm with sharptooth, sort of. You can call WaitForSingleObject with a 0 timeout for each object. The problem with doing this is that it has side-effects for some objects. For example, if you do this on a mutex and it succeeds, you not only know it wasn't the culprit, but you now own the mutex. If that isn't what you want, you'll have to know to immediately release it.
Any apporach you take is going to be subject to race conditions. Since you are outside of the "atomic" wait call, you could go through the process and discover that now they are all ready. You could get back a set of ready/unready that isn't what you actually had inside the wait call.
Ick.
None of this work, as WaitForSingleObject() will trigger an auto-reset event even when timeout is 0.
(Contrary to what MSDN says).
If your call returns WAIT_TIMEOUT it means that NONE of the objects you waited for was signalled..
I am working on writing a wrapper DLL to interface a communication DLL for a yokogawa WT1600 power meter, to a PC based automation package. I got the communication part to work but I need to thread it so that a 50ms scan time of the automation package can be maintained. (The Extended Function Block (EFB) Call will block the scan until it returns)
These are the steps I need to do.
Call EFB
EFB creates a thread to perform communication setup (takes about 200ms to do)
EFB returns EFB_BUSY while the thread is doing the work
3a. (automation program continues scanning until it comes back to the EFB call)
Call EFB passing in that it returned busy on the last call
EFB checks if the thread has returned
If the thread returned Then the EFB returns success, Else return EFB_BUSY
repeat 3a-6 until efb returns success
So my problem is, how do I create a thread that exists past the life of the function that called it? And how do I get that thread return value when I call back into the DLL?
EDIT #1
HeavyFunction::HeavyFunction^ hf; //HeavyFunction is a class that has a time consuming function in it
ThreadStart^ efbThreadDelegate;
Thread^ efbThread;
if( pEfbData->nBlockingRecall != DOEFB_BUSY ) {
hf = gcnew HeavyFunction::HeavyFunction;
hf->iiStart = (int)(pEfbData->uParams[0].dw);
hf->iiEnd = (int)(pEfbData->uParams[1].dw);
efbThreadDelegate = gcnew ThreadStart( hf, &HeavyFunction::HeavyFunction::iGetPrime );
efbThread = gcnew Thread( efbThreadDelegate );
efbThread->Start();
return DOEFB_BUSY;
}else if ( efbThread->IsAlive ) {
return DOEFB_BUSY;
}else {
uRetValue->dw = hf->iReturn;
return 0;
}
Will efbThread still have the same thread handle upon a subsequent call?
EDIT #2
I got it to work by creating a global HANDLE for a Mutex and a thread. Initializing the mutex in the init entry point (done upon dll loading) and creating the thread in the main function when a call is actually made to the dll.
I used the sample code from MSDN: Creating Threads as my model.
Any thread created (whether in a DLL or elsewhere) will not stop spontaneously. In particular, the function that created the thread may return. The new thread would still run even if the creator thread exited. That is, assuming it didn't hit the end of its entry function.
Windows threads return a DWORD when ready. To peek, call WaitForSingleObject on the thread handle with a 0 second timeout, and it that succeeds, call GetExitCodeThread .
I don't understand your whole "EFB" thing, neither what it is nor what it does, though. If it is doing funny things to normal Windows threads, all bets are off.