// JP opened flex table

Click to See Complete Forum and Search --> : Problem : Threads WILL NOT DIE!!


hanhao
April 16th, 2004, 10:50 AM
ok here's the situation

- i made a program that spawns a worker type thread ( thread A)
This thread sprawns 20 child worker threads (thread A_1, thread A_2 ...)
- thread A dies only after all the 20 child threads have returned
- Before all the threads return, the main user interface thread returns so that the prog is still responsive to the user.

the threads spawn as they should and according th VC++ debugger, they die properly when the child threads returns

The thread 0xFFF950A5 has exited with code 202 (0xCA).
The thread 0xFFF95485 has exited with code 202 (0xCA).
The thread 0xFFFA8865 has exited with code 202 (0xCA).
The thread 0xFFF96F81 has exited with code 202 (0xCA).
The thread 0xFFFAD82D has exited with code 202 (0xCA).
The thread 0xFFF8BDA9 has exited with code 202 (0xCA).
The thread 0xFFF90001 has exited with code 202 (0xCA).
The thread 0xFFF8D5C5 has exited with code 202 (0xCA).
The thread 0xFFF949FD has exited with code 202 (0xCA).
The thread 0xFFF94441 has exited with code 202 (0xCA).
The thread 0xFFF8B1C5 has exited with code 202 (0xCA).
The thread 0xFFFABD21 has exited with code 202 (0xCA).
The thread 0xFFF89D69 has exited with code 202 (0xCA).
The thread 0xFFF971F1 has exited with code 202 (0xCA).
The thread 0xFFF80095 has exited with code 202 (0xCA).
The thread 0xFFFECBAD has exited with code 202 (0xCA).
The thread 0xFFF95BF1 has exited with code 202 (0xCA).
The thread 0xFFFC1E59 has exited with code 202 (0xCA).
The thread 0xFFFFE325 has exited with code 202 (0xCA).
The thread 0xFFF98609 has exited with code 202 (0xCA).
The thread 0xFFF9BF8D has exited with code 202 (0xCA).
The thread 0xFFF972A9 has exited with code 1 (0x1). <== thread A


however i ran another program ( Iarsn TaskInfo2003 from download.com) to check out if the threads have died and HORRORS OF HORRORS!! :eek: :eek:

they were still alive, increasing in Arimetic progression everytime i press the button. Hence the more i use the program, the more UNDEAD threads there are hogging system resources.
So... how do i solve this stubbon problem??

- terminatethread isnt that elegant coz it doesnt flush everything out
- closehandle??
- exitthread?? I thought the child threads returns it's remaments memory is cleaned up cleaner than using exitthread?


I am using
- win98SE
- VC++ 6.0
- API style of coding, dunnno anything about MFC.(learning the basic API before going to MFC):eek: :eek: :eek: :eek: :eek:

kirants
April 16th, 2004, 11:39 AM
Not sure if this is the right forum. There is one on Multithreading, probably this post will get moved to that soon ;)

Anyways, it is not clear why since you do not mention what the worker threads do. Possibly something in the worker thread behaves differently and that is why it is still hanging around. Did you try putting traces in the worker thread proc and see where it is still blocked ?

OReubens
April 16th, 2004, 12:43 PM
The message "The thread 0x????? has exited..." is a message generated by Kernel32.dll to info you that the thread has indeed ended and has been removed from the system's active threads list. The thread is in effect 'dead' and does no longer execute. Thread local storage has been cleaned up, and the DllMain () with DLL_THREAD_DETACH of attached DLL's have been called to inform them that the thread has ended.

Now.. All this doesn't mean that every trace of the thread is gone from the system (yet). It's not supposed to be gone yet !!!
The handles to the threads are still 'alive', and can be used by a function like WaitForSingleObject() to allow other threads (most likely the main thread) to know the thread has ended.

TaskInfo2003 is showing that the handles are still 'live'. The actual threads however have ended (you can rest assured about that).

To REALLY remove the threads from the process, you need to explicitely call CloseHandle() on the threadhandle. Note however that once you have done this, the handle value is no longer valid, and a call to something like WaitForSingleObject() with this handle will fail. For this reason, it is sometimes needed to keep the handle open even long after the thread itself has ended.

Many programs (even big name ones) never bother to close thread handles. This isn't usually a big deal since when all threads have ended, the process is automatically shut down, and any open thread handles are automatically closed by the system.

If however you have a program that will create LOTS of threads during it's lifetime, keeping the handles open can consume a considerable amount of memory. For a service (especially one running on a server) I would never recommend leaving handles open, but would advice closing them as soon as possible.


Note that you can close the handle even when the thread is still running, this will not have any adverse effect on the running of the thread, it'll keep running normally. However if you do this, you loose the ability to check if the thread terminated via WaitForSingleObject() since it'll return WAIT_FAILED because the handle is no longer valid, or to abort the thread via TerminateThread (which is generally a bad idea anyway).

kirants
April 16th, 2004, 01:15 PM
Good point, oReubens.

So, you could so something like,


hThreadHandle = CreateThread(....)


... later on...


if(WAIT_OBJECT_0 == WaitForSingleObject(hThreadHandle....))
CloseHandle(hThreadHandle)

OReubens
April 16th, 2004, 01:24 PM
Yep.
Or if you don't need to wait... you can write stuff that will boggle the casual programmer... ;-)

CloseHandle( CreateThread(...) );

If the createThread fails, so will the closehandle, but if the create works, it'll close the handle immediately.

Not really recommended coding style, but a great piece of code for a programmers quiz if you ask them what the above will do.

kirants
April 16th, 2004, 01:29 PM
Originally posted by OReubens
CloseHandle( CreateThread(...) );
If the createThread fails, so will the closehandle, but if the create works, it'll close the handle immediately.


Just to add, that doesn't mean the thread is terminated instantly though. The threadproc is executed as normal.

Andreas Masur
April 16th, 2004, 02:05 PM
[Moved thread]

Andreas Masur
April 16th, 2004, 02:12 PM
From MSDN ('CreateThread'):

The thread object remains in the system until the thread has terminated and all handles to it have been closed through a call to CloseHandle.

From MSDN ('CloseHandle'):

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.

That basically answers your questions... :cool:

OReubens
April 16th, 2004, 02:29 PM
Just to add, that doesn't mean the thread is terminated instantly though. The threadproc is executed as normal.

Right, as I've stated in a previous post.

However, I've shown the sample to many programmers, and over half of them think the code will create the thread, and immediately terminate it (stopping it running).
A large percentile of the rest seems to think the code is invalid and either won't compile or won't run.

Even though threads seem to be commonplace these days, it's clear many programmers have absolutely no idea how to correctly deal with threads and possible race conditions.

Mick
April 16th, 2004, 02:45 PM
Originally posted by OReubens
Right, as I've stated in a previous post.

However, I've shown the sample to many programmers, and over half of them think the code will create the thread, and immediately terminate it (stopping it running).
A large percentile of the rest seems to think the code is invalid and either won't compile or won't run.

Even though threads seem to be commonplace these days, it's clear many programmers have absolutely no idea how to correctly deal with threads and possible race conditions.

hire the guy/gal that says, dunno, let me step though it in a debugger :p

hanhao
April 16th, 2004, 11:49 PM
hey thnx guys for the help! especially u OReubens.
now my prog doesnt have those useless handles anymore
i also found out that CreateEvent needs a closehandle too

:thumb:

OReubens
April 17th, 2004, 05:25 AM
i also found out that CreateEvent needs a closehandle too

Well, yes, just about everything that when created returns a handle has to be closed at some time. Not always through a call to CloseHandle though...

The MSDN docs are usually quite complete in that area, although they also seem somewhat incomplete/obscure in others.

In any case, always check the function in MSDN, and if it makes any mention of 'closing/destroying' the object, it's always best to explicitely provide a call to that as soon as you no longer need the object.

kirants
April 17th, 2004, 12:16 PM
Yeah... normally , keep an open eye for any API starting with Create...

The moment I put such a call, I make it a point to put a call to release it somewhere. Normally that's the practise I follow so as not to leave something dangling somewhere.

Gyannea
April 30th, 2004, 04:54 PM
Should one apply the "CloseHandle()' option to getting rid of a Window (when using the CreateWindow())? Perhpas in this case the DestroyWindow() function actually does all the cleanup.

Brian

kirants
April 30th, 2004, 04:59 PM
No.... not for CreateWindow. CloseHandle works on Kernel objects.

Anyways, my point was that anything explicitly created needs to be cleaned up somewhere.

So, if you CreateFile .. you would CloseHandle somewhere.
If you CreateEvent, you would CloseHandle somewhere.
If you CoCreateInstance and get an interface pointer, you would do a interface->Release somewhere.

Just a practise that applies to most , but not all, situations.

hanhao
February 26th, 2007, 08:59 PM
ok , i need to recap
so to get rid of a thread and stop it from running when it's halfway doing it's business, 2 APIs have to be called
1) TerminateThread(Handle of thread)
2) CloseHandle(Handle of thread)

correct?

Arjay
February 27th, 2007, 12:05 AM
Typically, you'll only use TerminateThread as a last resort. The preferred method is to 'signal' the thread to exit using an event. The main thread simply sets the event and the thread you wish to exit checks the event with a call to WaitForSingleObject( hExitEvent, 0 ).

Andreas Masur
February 27th, 2007, 09:53 AM
How to end a thread? (http://www.codeguru.com/forum/showthread.php?t=305166)

hanhao
February 27th, 2007, 09:27 PM
How to end a thread? (http://www.codeguru.com/forum/showthread.php?t=305166)

in that article it didnt tell us to call closehandle after terminatethread

i think besides terminatethread, another closehandle command is needed

can anyone comment on this?

hanhao
February 27th, 2007, 09:31 PM
Typically, you'll only use TerminateThread as a last resort. The preferred method is to 'signal' the thread to exit using an event. The main thread simply sets the event and the thread you wish to exit checks the event with a call to WaitForSingleObject( hExitEvent, 0 ).
good recommendaton

but the problem with that method is that the worker thread might be doing work in a loop and WaitForSingleObject would block the work in the loop

what we want is a method to tell the worker thread to stop working it's loop and retire

MikeAThon
February 27th, 2007, 10:16 PM
good recommendaton

but the problem with that method is that the worker thread might be doing work in a loop and WaitForSingleObject would block the work in the loop

what we want is a method to tell the worker thread to stop working it's loop and retire
And the method to do so is, as Arjay has explained, to signal the event that the thread is waiting on in WaitForSingleObject.

So... how do i solve this stubbon problem??
Have you seriously made no significant progress on this problem in the past three years :confused:

Mike

hanhao
February 28th, 2007, 02:10 AM
And the method to do so is, as Arjay has explained, to signal the event that the thread is waiting on in WaitForSingleObject.


Have you seriously made no significant progress on this problem in the past three years :confused:

Mike

no i have not
i am not a good programmer
it would take me 99999 years to solve a simple problem that's why i am humbly asking for help and comments


from what i know, MSDN says that WaitForSingleObject returns when one of the following occurs:

The specified object is in the signaled state.
The time-out interval elapses.


that means my worker thread has to have a polling mechanism in every loop like here
(from http://www.codeguru.com/forum/showthread.php?t=305166)

while(true)
{
// Check event for stop thread
if(::WaitForSingleObject(pParent->m_StopThread, 0) == WAIT_OBJECT_0)
{
// Set event
::SetEvent(pParent->m_WaitThread);

return 0;
}

now what i want is immediate stoppage of the thread, not stop on the next loop
plz comment

hanhao

Arjay
February 28th, 2007, 12:18 PM
no i have not
i am not a good programmer
it would take me 99999 years to solve a simple problem that's why i am humbly asking for help and comments


from what i know, MSDN says that WaitForSingleObject returns when one of the following occurs:

The specified object is in the signaled state.
The time-out interval elapses.


that means my worker thread has to have a polling mechanism in every loop like here
(from http://www.codeguru.com/forum/showthread.php?t=305166)

while(true)
{
// Check event for stop thread
if(::WaitForSingleObject(pParent->m_StopThread, 0) == WAIT_OBJECT_0)
{
// Set event
::SetEvent(pParent->m_WaitThread);

return 0;
}

now what i want is immediate stoppage of the thread, not stop on the next loop
plz comment

hanhaoThe best you are ever going to be able to do is exit the thread when you check the event. If you only check once per loop cycle, then it's going to exit after the check (wherever that happends to be in the loop).

The responsiveness of how the thread exits is directly related to how long the work takes in your thread. If the thread performs small amounts of work and then sleeps, you can use WaitForMultipleObjects to wait on the event that wakes the thread and the exit event:


HANDLE[] aEvents = { hWorkEvent, hExitEvent };

while( true )
{
switch( WaitForMultipleObjects( &aEvents[0],...., INFINITE ) )
{
case WAIT_OBJECT_0 + 0:
DoWorkHere( );
break;
case WAIT_OBJECT_0 + 1:
// Exit the thread
return;
}
}


If the function DoWorkHere( ) performs lengthy work (say like 5 minutes of work), you'll need to break the work down within the function and check whether to exit. One way to do this is to simply pass the exit event to the function.

HANDLE[] aEvents = { hWorkEvent, hExitEvent };

while( true )
{
switch( WaitForMultipleObjects( &aEvents[0],...., INFINITE ) )
{
case WAIT_OBJECT_0 + 0:
DoWorkHere( aEvents[1] );
break;
case WAIT_OBJECT_0 + 1:
// Exit the thread
return;
}
}

void DoWorkHere( Handle hExitEvent )
{
// Do some work here 1

// Check for exit event
if( WAIT_OBJECT_0 == WaitForSingleObject( hExitEvent, 0 ) ) return;

// Do some work here 2

// Check for exit event
if( WAIT_OBJECT_0 == WaitForSingleObject( hExitEvent, 0 ) ) return;

// Do some work here 3

// Check for exit event
if( WAIT_OBJECT_0 == WaitForSingleObject( hExitEvent, 0 ) ) return;

// Do some work here 4
}


Short of Terminating the thread (which is not recommended), there isn't anything that will cause the thread to exit immediately other than frequently checking for an exit event. This is only an issue on threads that perform lengthy work. If you structure your threads to perform small chunks of work (and then sleep), the thread will always be responsive to exit and you won't need as many exit event checks.

Andreas Masur
March 8th, 2007, 10:00 PM
in that article it didnt tell us to call closehandle after terminatethread

i think besides terminatethread, another closehandle command is needed

can anyone comment on this?
The FAQ only show the call to 'TerminateThread()' not a complete example as far as I remember. That is why there is no 'CloseHandle()' shown...

//JP added flex table