Friday, January 04, 2008

(Windows) What is the difference between a thread's HANDLE and its ID?

There seems to be some doubt amoung my peers over the use of a Thread ID, referred to here as a TID.

The most obvious difference between a HANDLE and a TID is that a HANDLE is specific to a process, whereas a TID is system wide.

A HANDLE is actually an unsigned int (whereas a UNIX file descriptor is a signed int) and is an index into the process's Handle Table, which is maintained by kernel.

A TID is a type of Client ID, the other type of Client ID being a PID (Process ID). TIDs and PIDs are generated in the same namespace and used by the kernel to identify these objects system wide.

So, why would you need the TID? You don't. At least, not often. A TID may be passed between processes, and another process can then get a HANDLE to that thread using the OpenThread() API.

Yes, you can manipulate threads in other processes - the caveat being that security may stop you, particularly in Windows Vista. Once you have a HANDLE to another thread you can do all those wonderful things, Suspend, Resume, Wait, GetExitCode, as you can if the thread is in the same process. One of the useful APIs in this context is PostThreadMessage(). This sentence is mis-leading, PostThreadMessage takes a TID, see comment from Hibou57 below.

BTW: make sure that HANDLE is closed, the thread cannot truly die until all HANDLEs to it are closed - that is how GetExitCodeThread() works. And you thought zombies only occurred on UNIX?

It is possible to use DuplicateHandle() to get a handle opened by another process, but that is far more painful than the MSDN implies.

2 comments:

Hibou57 said...

As the wording may be confusing, PostThreadMessage expects a Thread ID, not a Thread Handle :

BOOL PostThreadMessage
(DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM lParam);

By the way, this is the only case I know where a Thread ID is required.

Hibou57

Clive said...

Absolutly correct. I guess the reason is that PostThreadHandle can be used to communicate to threads in other processes, and there does not appear to be any security on this. Getting a handle to a thread requires access rights.