Why is beginthreadex thread argument variable not updating in parent thread

2714 views c++
-5

I have a thread which creates a hidden window for the purpose of receiving WinAPI messages based on power state. I need to get the HWND of the created window from the thread so that I can throw a WM_QUIT message to close the window and end the thread gracefully:

Main:

HWND hiddenWindowHandle = NULL;
HANDLE PowerWindowThreadHandle = (HANDLE)_beginthreadex(0, 0, &windowsPowerThread, (void*)&hiddenWindowHandle, 0, 0);

Thread:

unsigned int __stdcall windowsPowerThread(void* data)
{
    HWND hiddenWindowHandle = createHiddenWindow();
    HWND hwHandle = *(HWND*)data;
    hwHandle = hiddenWindowHandle;
    ...

The problem is that the hiddenWindowHandle is not being updated with the generated HWND.

I have verified in the thread that it's being created, and I've verified that I'm not trying to access the handle before the thread creates it.

What am I missing here?

answered question

How exactly do you make sure that the reading thread waits until the value is available and perform the necessary synchronization? If the first thing the other thread does is create that window, why not create the window in the main thread and pass the handle as argument to the thread function!? That'd eliminate all need for synchronization…

Because I print the validity of the HWND in the thread, and in main have a loop I break via a cin after which I print the value as it's seen from main. The thread shows a valid handle, I press enter, main doesn't. The solution you mention of course would work, but at the moment I want to know why this solution (which I've seen in multiple answers and forums) doesn't work.

1 Answer

7

Your code lacks the necessary synchronization. What you have here is a data race. Thus, what you get is strictly undefined behavior. What will most likely happen is that the compiler simply does not re-fetch the value of hiddenWindowHandle from memory in every iteration of the loop, since it can simply assume that the value does not change. One possible solution would be to make hiddenWindowHandle an std::atomic and have the main thread perform a busy wait until the value changes from NULL. Alternatively, you could put all access to the shared variable into a critical section locked by a mutex, or use a condition variable to wait for the value to be available.

posted this

Have an answer?

JD

Please login first before posting an answer.