ESP error when sending window messages between threads - c++

I have an Observer class and a Subscriber class.
For testing purposes, the observer creates a thread that generates fake messages and calls CServerCommandObserver::NotifySubscribers(), which looks like this:
void CServerCommandObserver::NotifySubscribers(const Command cmd, void const * const pData)
{
// Executed in worker thread //
for (Subscribers::const_iterator it = m_subscribers.begin(); it != m_subscribers.end(); ++it)
{
const CServerCommandSubscriber * pSubscriber = *it;
const HWND hWnd = pSubscriber->GetWindowHandle();
if (!IsWindow(hWnd)) { ASSERT(FALSE); continue; }
SendMessage(hWnd, WM_SERVERCOMMAND, cmd, reinterpret_cast<LPARAM>(pData));
}
}
The subscriber is a CDialog derived class, that also inherits from CServerCommandSubscriber.
In the derived class, I added a message map entry, that routes server commands to the subscriber class handler.
// Derived dialog class .cpp
ON_REGISTERED_MESSAGE(CServerCommandObserver::WM_SERVERCOMMAND, HandleServerCommand)
// Subscriber base class .cpp
void CServerCommandSubscriber::HandleServerCommand(const WPARAM wParam, const LPARAM lParam)
{
const Command cmd = static_cast<Command>(wParam);
switch (cmd)
{
case something:
OnSomething(SomethingData(lParam)); // Virtual method call
break;
case // ...
};
}
The problem is, that I see strange crashes in the HandleServerCommand() method:
It looks something like this:
Debug Error!
Program: c:\myprogram.exe
Module:
File: i386\chkesp.c
Line: 42
The value of ESP was not properly
saved across a function call. This is
usually the result of calling a
function declared with one calling
convention with a function pointer
declared with a different calling
convention.
I checked the function pointer that AfxBeginThread() wants to have:
typedef UINT (AFX_CDECL *AFX_THREADPROC)(LPVOID); // AFXWIN.H
static UINT AFX_CDECL MessageGeneratorThread(LPVOID pParam); // My thread function
To me, this looks compatible, isn't it?
I don't know, what else I have to look for. Any ideas?
I made another strange observation, that might be related:
In the NotifySubscribersmethod, I call IsWindow() to check if the window to which the handle points, exists. Apparently it does. But calling CWnd::FromHandlePermanent() returns a NULL pointer.

From afxmsg_.h:
// for Registered Windows messages
#define ON_REGISTERED_MESSAGE(nMessageVariable, memberFxn) \
{ 0xC000, 0, 0, 0, (UINT_PTR)(UINT*)(&nMessageVariable), \
/*implied 'AfxSig_lwl'*/ \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > \
(memberFxn)) },
So the signature is LRESULT ClassName::FunctionName(WPARAM, LPARAM), while yours is void ClassName::FunctionName(const WPARAM, const LPARAM). This should not compile, at least under VS2008 it doesn't.
What is your HandleServerCommand declaration in the CServerCommandSubscriber class (in the header file)?

To me, this looks compatible, isn't
it?
Syntactically it looks that way.
I don't know, what else I have to look
for. Any ideas?
Yes: I've had the same problem when compiling a plugin library with debug settings and used in a Release-compiled application.
Basically, the problem looks like a stack corruption.
Since you're running NotifySubscribers in a separate thread, consider using PostMessage (or PostThreadMessage) instead of SendMessage.
This may not be the actual cause of the crash, but the change should be made anyway (as you're switching threading contexts by using SendMessage with no guarding of the data whatsoever.

I eventually decided to do it without window messages and am now posting my workaround here. Maybe it will help someone else.
Instead of letting the observer post window messages to its subscribers, I let the observer put data into synchronized subscriber buffers. The dialog class subscriber uses a timer to periodically check its buffers and call the apropriate handlers if those aren't empty.
There are some disadvantages:
It's more coding effort because for each data type, a buffer member needs to be added to the subscriber.
It's also more space consuming, as the data exists for each subscriber and not just once during the SendMessage() call.
One also has to do the synchronization manually instead of relying on the observer thread being suspended while the messages are handled.
A - IMO - huge advantage is that it has better type-safety. One doesn't have to cast some lParam values into pointers depending on wParam's value. Because of this, I think this workaround is very acceptable if not even superior to my original approach.

Related

How does one move a std::unique_ptr between windows without risking a memory leak?

I want to do this project in C++ and be done with it once and for all:
select a movie from a list in one window and display the movie's details in another window.
I'd already arrived at Remy Lebeau's solution here and found his post because I'd realized the same limitation he did: it exposes the raw pointer to memory leakage.
(Please excuse my coding style).
MoviesWindow::MovieSelected( const unsigned int uint__MovieKey )
{ ...
std::unique_ptr<MovieBean> uptr__MovieBean = std::make_unique...
...
uptr__MovieBean->SetMovieTitle( row["MovieTitle"] );
uptr__MovieBean->SetYearReleased( row["YearReleased"] );
...
SendMessage( hwnd__MovieWindow, UWM_SendMovieBean, 0, (LPARAM) uptr__MovieBean->get() );
...
}
Fortunately, I have an advantage with SendMessage(): it won't end (releasing the std::unique_ptr) until the message handler returns, and the message handler's job is to clone the MovieBean.
MovieWindow::HandleUwmSendMovieBean( const HWND hwnd__MovieWindow, const UINT uint__WindowMessage, const WPARAM wParam, const LPARAM lParam )
{ UPTR__MovieBean = std::move( (*((MovieBean*) lParam).Clone() );
...
}
It seems the right way to do it is leave ownership of the std::unique_ptr with MovieSelected() until the actual moment of transfer by sending a reference to the handler, and using std::move on the reference.
MoviesWindow::MovieSelected( const unsigned int uint__MovieKey )
{ ...
SendMessage( hwnd__MovieWindow, UWM_SendMovieBean, 0, (LPARAM) &uptr__MovieBean );
...
}
But I cannot figure out how to get the reference out of lParam and into std::move. This would seem to be the one, but nope.
MovieWindow::HandleUwmSendMovieBean( const HWND hwnd__MovieWindow, const UINT uint__WindowMessage, const WPARAM wParam, const LPARAM lParam )
{ UPTR__NewMovieBean = std::move( reinterpret_cast<std::unique_ptr<MovieBean>*>( lParam ) );
...
}
I've tried every combination I can think of and ensured that the address sent is the address received and supplied to std::move. All I get are constant compiler errors (including a now-much-hated one about std::remove_reference), and crashes. Any insight would be appreciated.
SendMessage and unique_ptr are definitely not made for each other. I can give lots of hints here, but the best thing to do is to not be smuggling smart pointers through HWND messages.
I don't know what a UWM_SendMovieBean, but I'm guessing that's a custom windows message you either based of off WM_USER or RegisterWindowsMessage. So what you are really doing sounds like you are trying to signal another code component with SendMessage instead of a formal contract between the backing classes of both windows. It's not the worst thing ever to do this, but with a class as specialized as unique_ptr, it gets much harder to pull off.
The cheap and easy thing to do would be to have both windows share the row data structure that you have. Then your send message simply sends the uint__MovieKey as the WPARAM or LPARAM of your custom message.
But if you were on my team, and we were building this app together, I'd give you the crash course in Model-View-Presenter (and other MVC designs) that make these types of feature designs more maintainable.
I got the answer in two more tries:
MovieWindow::HandleUwmSendMovieBean( const HWND hwnd__MovieWindow, const UINT uint__WindowMessage, const WPARAM wParam, const LPARAM lParam )
{ UPTR__NewMovieBean = std::move( *((std::unique_ptr<MovieBean>*) lParam) );
...
}
Basically, sending the address of the std::unique_ptr<MovieBean> meant I was sending a pointer, so I needed to std::move(...) what the pointer was pointing to. It works fine.
This still seems sound to me: I'm leaving the MovieBean protected by a smart pointer while it's "in flight". It's effectively just a pass-by-reference that doesn't violate C++ Core Rule 33: Take a unique_ptr<widget>& parameter to express that a function reseats the widget.
The substantial problem in this usage is that my message handler is also the signal to read the MovieBean's copious information into the various CommonControls of the MovieWindow. Message handlers are supposed to be quick. The better approach is what #selbie suggested: the formal contract between the backing classes.

Connecting callback to thread

I am calling a library function which also need a callback function as its only argument. It is time consuming function and the callback is called frequently to pass messages to the client (my application) to display. The problem is I want to copy the message and pass it onto the main thread for display but because it is callback function, I see no other way but to use globals to do that and that's what I am trying to avoid/make better.
The callback is static member function of my CTestDlg which alrady has m_hWnd member where I want to post the messages. However for the sake of callback I have yet defined another static g_hWnd member so my callback can access it and post message to it. This part doesn't look very nice to me but my callback routine is collecting messages wonderfully.
My callback function is the following
void CTestDlg::OnNotify (int code, const char * msg)
{
char * message = NULL; // to copy the message
message = new char[ strlen( msg) + 1 ]();
strcpy_s( message, strlen(msg) +1, msg );
PostMessageA( g_hWnd, ID_NOTIFY_MSG, code, (LPARAM) message );
}
I am running the library call in a separate thread and because it is callback to that function, it also runs in the same thread. Is there a better way to change hand in this callback function and pass the message to main thread or a particularly window to display?
If your callback is a static method, it has no access to instance data, so you must store your state data (the main window handle, in your case) in a static or global variable.
You can move the handle from a global variable to a static CTestDlg::s_hWnd variable.

Multithreading with _beginthread and CreateThread

I try to write a Multithreading WIN32 Application in C++, but due to i get difficulties.
One of the Window Procedure creates a Thread, which manages the output of this window. If this Window Procedure receives a message (from the other Window Procedures), it should transmit it to their Thread. At the beginning i worked with the _beginthread(...) function, what doesn't work.
Then i tried it with the CreateThread(...) function, and it worked? What did i do wrong?
(My English isn't so good, i hope you understand my problem)
Code with CreateThread(...):
DWORD thHalloHandle; // global
HWND hwndHallo; // Hwnd of WndProc4
...
LRESULT APIENTRY WndProc4 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static PARAMS params ;
switch (message)
{
case WM_CREATE: {
params.hwnd = hwnd ;
params.cyChar = HIWORD (GetDialogBaseUnits ()) ;
CreateThread(NULL, 0, thHallo, &params, 0, &thHalloHandle);
return 0 ;
}
...
case WM_SPACE: {
PostThreadMessage(thHalloHandle, WM_SPACE, 0, 0);
return 0;
}
...
}
Code with _beginthread(...):
...
case WM_CREATE: {
params.hwnd = hwnd ;
params.cyChar = HIWORD (GetDialogBaseUnits ()) ;
thHalloHandle = (DWORD)_beginthread (thHallo, 0, &params) ;
return 0;
}
...
case WM_SPACE: {
PostThreadMessage(thHalloHandle, WM_SPACE, 0, 0);
return 0;
}
...
thHallo for CreateThread:
DWORD WINAPI thHallo(void *pvoid)
{
static TCHAR *szMessage[] = { TEXT(...), ...};
// Some Declaration
pparams = (PPARAMS) pvoid;
while(!pparams->bKill)
{
MsgReturn = GetMessage(&msg, NULL, 0, 0);
hdc = GetDC(pparams->hwnd);
if(MsgReturn)
{
switch(msg.message)
{
// case....
}
}
}
return 0;
}
thHallo for _beginthread(...):
void thHallo(void *pvoid)
{
...
// The Same like for CreateThread
...
_endthread();
}
The _beginthread/ex() function is proving to be radically difficult to eliminate. It was necessary back in the previous century, VS6 was the last Visual Studio version that required it. It was a band-aid to allow the CRT to allocate thread-local state for internal CRT variables. Like the ones used for strtok() and gmtime(), CRT functions that maintain internal state. That state must be stored separately for each thread so that the use of, say, strtok() in one thread doesn't screw up the use of strtok() in another thread. It must be stored in thread-local state. _beginthread/ex() ensures that this state is allocated and cleaned-up again.
That has been worked on, necessarily so when Windows 2000 introduced the thread-pool. There is no possible way to get that internal CRT state initialized when your code gets called by a thread-pool thread. Quite an effort btw, the hardest problem they had to solve was to ensure that the thread-local state is automatically getting cleaned-up again when the thread stops running. Many a program has died on that going wrong, Apple's QuickTime is a particularly nasty source of these crashes.
So forget that _beginthread() ever existed, using CreateThread() is fine.
There's a serious problem with your use of PostThreadMessage(). You are used the wrong argument in your _beginthread() code which is why it didn't work. But there are bigger problems with it. The message that is posted can only ever be retrieved in your message loop. Which works fine, until it is no longer your message loop that is dispatching messages. That happens in many cases in a GUI app. Simple examples are using MessageBox(), DialogBox() or the user resizing the window. Modal code that works by Windows itself pumping the message loop.
A big problem is the message loop in that code knows beans about the messages you posted. They just fall in the bit-bucket and disappear without trace. The DispatchMessage() call inside that modal loop fails, the message you posted has a NULL window handle.
You must fix this by using PostMessage() instead. Which requires a window handle. You can use any window handle, the handle of your main window is a decent choice. Better yet, you can create a dedicated window, one that just isn't visible, with its own WndProc() that just handles these inter-thread messages. A very common choice. DispatchMessage() can now no longer fail, solves your bug as well.
Your call to CreateThread puts the thread ID into thHalloHandle. The call to _beginthread puts the thread handle into thHalloHandle.
Now, the thread ID is not the same as the thread handle. When you call PostThreadMessage you do need to supply a thread ID. You only do that for the CreateThread variant which I believe explains the problem.
Your code lacks error checking. Had you checked for errors on the call to PostThreadMessage you would have found that PostThreadMessage returned FALSE. Had you then gone on to call GetLastError that would have returned ERROR_INVALID_THREAD_ID. I do urge you to include proper error checking.
In order to address this you must first be more clear on the difference between thread ID and thread handle. You should give thHalloHandle a different name: thHalloThreadId perhaps. If you wish to use _beginthread you will have to call GetThreadId, passing the thread handle, to obtain the thread ID. Alternatively, use _beginthreadex which yields the thread ID, or indeed CreateThread.
Your problem is that you need a TID (Thread Identifier) to use PostThreadMessage.
_beginthread doesn't return a TID, it return a Thread Handle.
Solution is to use the GetThreadId function.
HANDLE hThread = (HANDLE)_beginthread (thHallo, 0, &params) ;
thHalloHandle = GetThreadId( hThread );
Better Code (see the documentation here)
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, thHallo, &params, 0, &thHalloHandle ) ;

GetWindowLongPtr sets Error to "Class already Exists"

In my Windows API wrapper, I can choose to have a message box come up when there's an error. I have one that I can't really pin down though.
Here's my main function:
int main()
{
Window win; //create default window with default class (name changes each new instance)
return messageLoop(); //the familiar GetMessage() while loop, returns msg.wParam
}
This all works fine, but when I close my window (just tested via X button), I get the following message (this is what I get when I copy the message box):
---------------------------
Error
---------------------------
File: "G:\programming\v2\wwbasewindow.h"
Function: _fakeWndProc
Line: 61
Error Code: 1410
Error: Class already exists.
---------------------------
OK
---------------------------
Now it's crystal clear where this error is coming from, but not exactly why. Here's the _fakeWndProc function. The whole wrap (function, args) syntax checks GetLastError() after that function is called. This is why you don't see error checking.
LRESULT CALLBACK BaseWindow::_fakeWndProc (msgfillparams) //trick procedure (taken from someone's gui wrapper guide)
{
BaseWindow * destinationWindowPtr = 0; //for which window message goes to
//PROBLEM IN THE FOLLOWING LINE (gets a pointer to the window, set when it's created)
destinationWindowPtr = (BaseWindow *)wrap (GetWindowLongPtr, hwnd, GWLP_USERDATA);
if (msg == WM_COMMAND && lParam != 0) //if control message, set destination to that window
destinationWindowPtr = (BaseWindow *)wrap (GetWindowLongPtr, (hwin)lParam, GWLP_USERDATA);
if (destinationWindowPtr) //check if pointer is valid
return destinationWindowPtr->_WndProc (hwnd, msg, wParam, lParam); //call window's procedure
else
return wrap (DefWindowProc, hwnd, msg, wParam, lParam); //call default procedure
}
I'm just wondering why this call is (trying to create a class?) That aside, I tried checking the error codes from the time a WM_CLOSE message comes along. I output the code before the line, and after. This is what comes up:
Before: 0
After: 0
--->Before: 0
--->Before: 1410
After: 1410
Before: 1410
After: 1410
...
This puts the topping on my confusion, as this implies that the function calls SendMessage somewhere inside. But why wouldn't it do the same for any others?
The error itself doesn't make much of a difference, as the program ends right after, but I don't want it hanging around. How can I deal with it?
Note:
I just tried not calling PostQuitMessage (0); when WM_DESTROY came up, and created 2 windows. Both of them gave the same error when closing, so it's not necessarily the end of the program anyways.
Also, each one gave an error 1400 (Invalid window handle) too, but only when I didn't call PostQuitMessage. This error originated from the call to DefWindowProc in those windows' respective window procedures. Any ideas on that one either?
Edit:
Due to request, here is the code for wrap:
// pass along useful error information (useless constants within error function)
#define wrap(...) Wrap (__FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
// cstr == char *
// con == const
// sdword == int (signed dword)
// version if return value of API function is not void
template<typename TRet, typename... TArgs>
typename std::enable_if<!std::is_void<TRet>::value, TRet>::type
Wrap(con cstr file, const char * const func, con sdword line, TRet(*WINAPI api)(TArgs...), TArgs... args)
{
TRet result = api(std::forward<TArgs>(args)...); //call API function
if (GetLastError()) __wwError.set (GetLastError(), file, func, line); //set variables and create message box
return result; // pass back return value
}
// version if return value is void
template<typename... TArgs>
void Wrap(con cstr file, const char * const func, con sdword line, void(*WINAPI api)(TArgs...), TArgs... args)
{
api(std::forward<TArgs>(args)...);
if (GetLastError()) __wwError.set (GetLastError(), file, func, line);
}
I'm 100% sure this and __wwError.set() work though. All other functions wrapped with this give appropriate message boxes.
Your calls to GetLastError are simply incorrect. You cannot indiscriminately call GetLastError like that. You should only call it when the API call documentation says that it is valid to do so. Usually this will be if the API call reports failure.
The calls to DefWindowProc are a fine illustration of how this can go wrong. The documentation for DefWindowProc does not make any mention of a way for the function to report failure. And it makes no mention of calling GetLastError. Thus your calls to GetLastError should not be made and are returning undefined, meaningless values.
Since there is no single common mechanism for a Win32 function to report failure, your attempt to wrap all Win32 API calls with a single common error handling routine is doomed to failure.
What you need to do is to treat each API call on its own merits, and write error checking appropriate for that API call. Since you are using C++ I would recommend you make use of exceptions here. Write a function, ThrowLastWin32Error say, that you call whenever an API function reports failure. The implementation of ThrowLastWin32Error would call GetLastError and then call FormatMessage to obtain a textual description before throwing a suitably descriptive exception. You would use it like this:
if (!CallSomeWin32Function())
ThrowLastWin32Error();
But the main point is that you do need case-by-case checking of function success since different Win32 functions report failure in different ways.

How to send a string via PostMessage?

Inside my app, I want to send a message to a dialog from a different thread.
I want to pass an std::exception derived class reference to the dialog.
Something like this:
try {
//do stuff
}
catch (MyException& the_exception) {
PostMessage(MyhWnd, CWM_SOME_ERROR, 0, 0); //send the_exception or the_exception.error_string() here
}
I want to receive the message in my dialog and show the error that is in the_exception.error_string()
LPARAM CMyDlg::SomeError(WPARAM, LPARAM)
{
show_error( ?????
return 0;
}
passing the std::string the_exception.error_string() using PostMessage would also be ok, I guess.
You can't pass the address of the string in PostMessage, since the string is probably thread-local on the stack. By the time the other thread picks it up, it could have been destroyed.
Instead, you should create a new string or exception object via new and pass its address to the other thread (via the WPARAM or LPARAM parameter in PostMessage.) The other thread then owns the object and is responsible for destroying it.
Here is some sample code that shows how this could be done:
try
{
// do stuff
}
catch (const MyException& the_exception)
{
PostMessage(myhWnd, CWM_SOME_ERROR, 0, new std::string(the_exception.error_string));
}
LPARAM CMyDlg::SomeError(WPARAM, LPARAM lParam)
{
// Wrap in a unique_ptr so it is automatically destroyed.
std::unique_ptr<std::string> msg = reinterpret_cast<std::string*>(lParam);
// Do stuff with message
return 0;
}
As long as you are within a process simply passing a void* pointer and some care on object lifetime are enough.
If is SendMessage you can pass it in LPARAM as a void* cast, and the client uncast it back to your string type. Because SendMessage is synchronous, you are safe:
If the specified window was created by
the calling thread, the window
procedure is called immediately as a
subroutine. If the specified window
was created by a different thread, the
system switches to that thread and
calls the appropriate window
procedure. Messages sent between
threads are processed only when the
receiving thread executes message
retrieval code. The sending thread is
blocked until the receiving thread
processes the message
If you want to use PostMessage then you'll have to do an explicit hand off because the call is asynchronous: make a copy of the string on the heap and by calling the PostMessage you have passed the delete responsability to the calee (the dialog).
If you go out of process (MyhWnd belongs to a different process) then is a whole different story and you'll have to marshal your message into something like a global atom.
As long as you know that your window (or instance of CMyDlg) will still be around after posting the message you could simply store the error string in a member variable and read from this in your message handler.