thread calls

Started by
7 comments, last by LessBread 17 years, 11 months ago
What does this mean to you guys? The bold part at least...
Quote: It is safer to use _beginthreadex than _beginthread. If the thread generated by _beginthread exits quickly, the handle returned to the caller of _beginthread might be invalid or, worse, point to another thread. However, the handle returned by _beginthreadex has to be closed by the caller of _beginthreadex, so it is guaranteed to be a valid handle if _beginthreadex did not return an error. You can call _endthread or _endthreadex explicitly to terminate a thread; however, _endthread or _endthreadex is called automatically when the thread returns from the routine passed as a parameter. Terminating a thread with a call to endthread or _endthreadex helps to ensure proper recovery of resources allocated for the thread. _endthread automatically closes the thread handle (whereas _endthreadex does not). Therefore, when using _beginthread and _endthread, do not explicitly close the thread handle by calling the Win32 CloseHandle API. This behavior differs from the Win32 ExitThread API.
Doesn't that contradict itself? So I want a thread to spawn using _beginthreadex. The thread will hopefully finish on its own. Do I need to call _endthreadex with my main process after the spawned thread has finished? Is it okay if _endthreadex is called multiple times (whether is be from the main process that spawned the thread or the thread upon returning)? Also if the thread stalls, a call to _endthreadex will instantly end the thread regardless of its state, right? And I'm assuming I can pass the return value from _beginthreadex to WaitForSingleObject, is that right? Thanks for the help.
-------Harmotion - Free 1v1 top-down shooter!Double Jump StudiosBlog
Advertisement
The thread that calls _beginthreadex should call _endthreadex when the new thread finishes. Here's a usage example. You can easily find more usage examples using google. Yes, you can use the handle returned by _beginthreadex with WaitForSingleObject. Remember though, Wait functions essentially put their callers to sleep. So if you want the launcher thread to perform other tasks, do them before calling WaitForSingleObject on the new thread handle. You can learn more than you ever wanted to know about beginthreadex and endthreadex here.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Well, the first link uses CloseHandle instead of _endthreadex. Have yet to read the 2nd. I feel like I'm taking crazy pills.

Edit: So the 2nd site explains it a little better. The thread needs to be ended AND closed. Is that right? When the thread func returns, _endthreadex is implicitly called, then someone needs to call CloseHandle on the thread. Am I still on the right track? And finally, what if the thread stalls and needs to be closed down forcefully with CloseHandle... should _endthreadex be called before CloseHandle?

Edit2: After some more research, all of the above seems correct. Back to my original set of questions: is it okay to call _endthreadex multiple times? What if I wait on the thread for a second, then the process task switches to the thread and it returns (calling _endthreadex), then we switch back to the main thread that calls _endthreadex because it doesn't think the thread is closed yet. Is that a problem and how can it be fixed (without critical sections)?

[Edited by - blaze02 on May 5, 2006 7:36:50 PM]
-------Harmotion - Free 1v1 top-down shooter!Double Jump StudiosBlog
Quote:Original post by blaze02
Well, the first link uses CloseHandle instead of _endthreadex. Have yet to read the 2nd. I feel like I'm taking crazy pills.

Edit: So the 2nd site explains it a little better. The thread needs to be ended AND closed. Is that right? When the thread func returns, _endthreadex is implicitly called, then someone needs to call CloseHandle on the thread. Am I still on the right track? And finally, what if the thread stalls and needs to be closed down forcefully with CloseHandle... should _endthreadex be called before CloseHandle?

Edit2: After some more research, all of the above seems correct. Back to my original set of questions: is it okay to call _endthreadex multiple times? What if I wait on the thread for a second, then the process task switches to the thread and it returns (calling _endthreadex), then we switch back to the main thread that calls _endthreadex because it doesn't think the thread is closed yet. Is that a problem and how can it be fixed (without critical sections)?


It should be ok to call _endthreadex multiple times. It's ok to call CloseHandle multiple times on the same handle, that is, nothing happens by it. This is a determination that you can make empirically by simply repeating the call in a dummy program (for example, the usage example from above). Then run the program and see if it faults. In the scenario that you present, it seems to me that when the process thread calls _endthreadex, the call will simply return if the thread has already finished. You can also use GetExitCodeThread to get the termination status of the thread and determine whether or not _endthreadex is needed.


"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Quote:Original post by LessBread
It's ok to call CloseHandle multiple times on the same handle, that is, nothing happens by it.


Ummm, no. If the handle value gets reallocated by the OS between the two calls to CloseHandle you will end up closing some random handle and who knows what will happen.
-Mike
Win32 threads need to be terminated and your handle to it needs to be closed. These two events can happen in either order. (This is very different from posix.)

_beginthread/_endthread are broke, use the ex versions.

_endthreadex cleans up CRT resources and kills the executing thread - you don't call it from the thread that calls _beginthreadex. You may call it from the thread that _beginthreadex creates. It will be called automatically if the thread exits normally (not certain what happens if the thread generates an exception).

The reason to use _beginthreadex instead of CreateThread(Ex) is if you use CRT (C run-time) functions. If it's a pure Win32 application you can use CreateThread (which is what _beginthreadex wraps).

If you just want to "Fire & Forget" the thread; create it with _beginthread then close the handle it returns right away. However, when thread 0 terminates (main/WinMain), it takes out any other running threads so you might want to wait, say, 5 seconds (using WaitForSingleObject or WaitForMultipleObjects) to give your worker threads a chance to finish what they are doing. Then close the thread handles.
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Quote:Original post by Anon Mike
Quote:Original post by LessBread
It's ok to call CloseHandle multiple times on the same handle, that is, nothing happens by it.


Ummm, no. If the handle value gets reallocated by the OS between the two calls to CloseHandle you will end up closing some random handle and who knows what will happen.


Try it out for yourself. CloseHandle calls occur in the process, they don't affect handles in other processes. There could be a problem if the process creates large number of new objects in the time between calls, but that isn't likely. However, calling CloseHandle twice while running in a debugger will throw according to MSDN: CloseHandle.

Here's a relevant tidbit from the remarks section:

"Closing a thread handle does not terminate the associated thread. To remove a thread object, you must terminate the thread, then close all handles to the thread."

// edit: don't get me wrong here, I'm not saying that uncessary calls to CloseHandle are good - just that they aren't the worst things that could happen - and in context, that it probably won't hurt to call _endthreadex on the thread handle in question.

[Edited by - LessBread on May 5, 2006 10:11:29 PM]
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
The kind of handles we're talking about here are process-local. The kernel keeps track of allocated handle values and can reallocate the value to some other object if you close the first handle value. Yes, calling CloseHandle on an unallocated handle value isn't particularly harmful however that is not the scenario I was talking about. I was talking about:

Thread 1: Creates a thread, gets back a handle (say it's 0x40)
Thread 1: CloseHandle(0x40)
Thread 2: CreateEvent() (or whatever), gets back 0x40 (handle value reused)
Thread 1: CloseHandle(0x40)
Thread 2: do something with it's event handle - ERROR_INVALID_HANDLE.

It's kind of like the people that say it's ok to read from a pointer after you've called free/delete on it. Yeah, it'll probably work 99% of the time but it's at best an extremely poor practice and at worst can give very subtle and impossible to reproduce bugs.

Note that the system can create threads in your process for it's own use. Just because none of your threads are allocating handles doesn't mean they're not being allocated by somebody else.
-Mike
My initial remark pertained to unallocated handles, but would the kernel reuse a handle value so readily? Wouldn't it make more sense to exhaust the range before reusing values (precisely to minimize this kind of problem)?

I can see why repeat calls to CloseHandle would throw in a debugger, it acts like an assert, alerting the programmer to a code flaw.

"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man

This topic is closed to new replies.

Advertisement