Click here to Skip to main content
15,938,578 members
Articles / Desktop Programming / Win32
Tip/Trick

The Current Thread Handle

Rate me:
Please Sign up or sign in to vote.
5.00/5 (5 votes)
27 Dec 2022MIT1 min read 15.3K   7   2
What to do when you want to use the current thread handle
This tip shows a side effect of GetCurrentThread and explains what to do when you need to avoid that.

Introduction

When you need to get a handle to the current thread, you can use GetCurrentThread which gives you a pseudo handle which you don't need to close because it is not a real reference counted handle. This is mentioned clearly in the documentation. However, I recently bumped my head against this. I wanted to share it so that others can avoid having to chase this down.

My Headbump

Consider the following example:

C++
DWORD worker(void* ctx)
{
    std::cout << "Thread id: " << GetThreadId((HANDLE)ctx) << std::endl;
    return 0;
}

int main()
{
    HANDLE hMainThread = GetCurrentThread();
    std::cout << "Thread id: " << GetThreadId(hMainThread) << std::endl;

    HANDLE hThread = CreateThread(NULL, 0, worker, hMainThread, 0, NULL);
    WaitForSingleObject(hThread, INFINITE);    
}

This is what happens:

Without thinking, I had assumed that the pseudo handle was just a weak copy of the actual handle (a non reference counted copy of the current handle), and I could reference it in a worker thread. Instead, it is a special constant that literally means 'when this handle value is supplied, use the current thread'. And if you pass that special value to another thread, then that value will translate to the thread handle of 'that' thread.

If you read the documentation, then this is exactly what it says. Only I didn't stop to think about what that actually meant.

Getting the Real Thread Handle

If you want to get a real handle that you can pass to another thread, do this:

C++
HANDLE hMainThread = NULL;
if (!DuplicateHandle(
    GetCurrentProcess(),
    GetCurrentThread(),
    GetCurrentProcess(),
    &hMainThread,
    0,
    FALSE,
    DUPLICATE_SAME_ACCESS)) {
    cout << "Error " << GetLastError() << " cannot duplicate main handle." << endl;
    return GetLastError();
}

Of course, when you do this, you get a HANDLE value that you do need to close when you no longer need it.

Points of Interest

As I said, this is nothing earth shattering and the documentation explains this. However, it took me a while before I understood why my APCs were scheduled in the wrong thread, so perhaps I can save others the trouble. :)

History

  • 27th December, 2022: First version

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer
Belgium Belgium
I am a former professional software developer (now a system admin) with an interest in everything that is about making hardware work. In the course of my work, I have programmed device drivers and services on Windows and linux.

I have written firmware for embedded devices in C and assembly language, and have designed and implemented real-time applications for testing of satellite payload equipment.

Generally, finding out how to interface hardware with software is my hobby and job.

Comments and Discussions

 
Questionit is useful Pin
Alexander Khot29-Dec-22 0:22
professionalAlexander Khot29-Dec-22 0:22 
PraiseThanks for sharing Pin
David On Life28-Dec-22 23:01
David On Life28-Dec-22 23:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.