DLL crashes app after reuse - c++

I use an application that uses mdi and a script can be attached to, and detached from, a mdi window to be run/stopped on demand; this script loads my dll that does some work; it does fine so; however, when I detach the script still all is fine and the application should unload the dll (and it calls dllmain with the appropriate thread_attach/detach and process_attach/detach operations). Now if I try to re-attach the script to the winow, or to attach it to another window, after the dll has been in use once - the main application crashes. I have isloated the problem to a thread that is created by the dll; the tread crates a window; so, I create the thread like so:
if (!hThread) hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
and, when the script is detached it shuts down the thread like so (no matter if the commented-out lines are uncommented-out):
SendMessage(hWnd, WM_DESTROY, 0, 0);
//TerminateThread(hThread, 0);
//WaitForSingleObject(hWndThread, INFINITE);
CloseHandle(hThread);
hThread = NULL;
I'm at a loss here as to why the main app crashes. A different thread (i.e. one that would simply sleep for a second and loop, will do no harm. What gives?

Ok, here are some ideas:
You said your thread opens a window. Do you run a message loop in the thread function, or you expect your window to be serviced by some other message loop?
If you are running your own message loop in the thread, then exiting the loop may or may not happen, depending on how you have written it. If you use something like:
while(GetMessage(&msg, ...) // msg loop in the thread function
{
....
}
DestroyWindow(hWnd); // see comment below
then this requires a WM_QUIT and not WM_DESTROY to exit. Anyway, the best is to send your window a WM_QUIT and after exiting the message loop then call DestroyWindow() to destroy it properly.
Quoting from MSDN:
DestroyWindow function
Destroys the specified window. The function sends WM_DESTROY and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus from it. The function also destroys the window's menu, flushes the thread message queue, destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if the window is at the top of the viewer chain
After posting WM_QUIT message to your window, your main thread should wait for the window thread to exit. Here is some relevant code:
SendMessage(hWnd, WM_QUIT, 0, 0); // send your quit message to exit the msg loop
if (WaitForSingleObject(hThread, 5000) != WAIT_OBJECT_0) // wait up to 5 seconds
{
TerminateThread(hThread, -1); // bad! try to never end here
}
I hope this helps. I use this in a threaded log viewer that uses a window to display log messages.

Related

Can I manually invoke processing of window messages in the main thread in a win32 application?

I have a Win32 MFC application that does some processing in a loop. Currently the window stops redrawing while the loop is running. Can I somehow allocate time to the message queue inside my loop or will I have to move the processing to a different thread to free up the main thread for message handling?
You can use the following code snippet to process messages:
MSG msg;
if (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (::GetMessage(&msg, NULL, 0, 0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
But it is always better to have separate thread for long operations to prevent blocking of main app thread.

MFC main UI thread workings and modal dialogs

First let me say that I have roughly searched stackoverflow for this, but couldn't find a specific answer.
My question is rather theoretical and there is no problem with the running of any code. Please consider a simple MFC application with a timer event and a button (attached to an OnClick event).
void SampleDlg::OnTimer(UINT_PTR nIDEvent)
{
CString msg;
msg.Format("time: %lld, tid: %d", (int64_t)time(0), GetCurrentThreadId());
SetWindowText(msg);
}
My intuition suggests that if I sleep inside the OnClick event, main UI thread should hang and timer events shouldn't kick in.
void SampleDlg::OnClick()
{
Sleep(10000);
}
That is fine, however if I show a new modal dialog inside the OnClick, the timer events still happen. What is different here?
void SampleDlg::OnClick()
{
CString msg;
msg.Format("tid: %d is waiting...", GetCurrentThreadId());
::MessageBox(GetSafeHwnd(), msg, "Msg", 0);
// at this point msgbox tells us that thread with tid is waiting
// thread with tid wont reach this line until msgbox is closed
}
Edit: I have included GetCurrentThreadId() calls to make what i want to ask more clear.
When I run the code above, both msgbox and the window title gives me the same thread-id: 22012 (for example). My question is, what is the value of PC/IP (program counter or instruction pointer) of thread 22012 when msgbox is being shown?
The MessageBox has it's own message loop, like all modal dialogs.
So it uses PeekMessage/GetMessage. WM_TIMER and WM_PAINT messages are pseudo messages that are generated when the message loop executes.
This means that MessageBox internally calls GetMessage or PeekMessage and this causes the effect that the thread still executes MessageBox, but new messages are delivered to you windows.

which thread processes messages of a spesific hwnd

I have two threads and I call CreateWindowEx function from different processes. The two threads are MainThread and Action.dlu.
Action.dlu creates a window and holds a buffer associated with the window. Whenever I resize the window, window messages are acumulated untill I process and deleted them from queue with the fallowing lines.
while(PeekMessage(&msg, mHWnd, 0U, 0U, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Action.dlu uses the buffer associated with the window so I process messages when I finish using buffers. However, when I create the window from MainThread, WM_SIZE message gets immediately triggered. I mean it doesn't wait for me to process messages. My WNDPROC calback function gets called from MainThread. Is there a way to make a specific process the owner of the window ? This way I can keep processing messages wherever I want.

Win32 windowless application - wait for program exit

I have a windowless application whose only purpose is to install a 32 bit hook DLL file and wait until the parent program (a 64-bit program) exits. The 64-bit program is written in C#, and the windowless application is written in C++. I originally had this GetMessage loop which held the program open:
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
I was closing the C++ application using the Process.Kill method in C#, but I found out that that isn't allowing the C++ application to close cleanly. Also, if the C# application crashed, the C++ application would stay open forever. I made the C++ application check to see if the C# application is still running, using this loop:
while(true)
{
if(PeekMessage(&msg, NULL, 0, 0, true))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(!isMainProgramRunning())
break;
Sleep(1000);
}
For some reason the Sleep causes problems. The hooks installed by the DLL file are WH_CBT and WH_KEYBOARD. Whenever I press a key while the C++ application is running with this loop, the keys just get eaten up. Removing the Sleep makes it work fine, but, as expected, it uses 100% CPU, which I don't want. I tried removing the message loop altogether and instead using WaitForSingleObject with an infinite timeout on a thread which would end when isMainProgramRunning returned false. This basically locks up the whole computer.
I don't really understand why GetMessage, which, as far as I saw, never returned, but suspended the main thread indefinitely, didn't cause these problems yet WaitForSingleObject causes every application to freeze when I click on it. How can I get the C++ application to stay open until the C# application closes?
Edit:
Since it's been pointed out to me that sleeping in a message pump is bad, let me ask this: Is there a way to specify a timeout on the message waiting, so the program isn't waiting indefinitely for a message, but rather, will wait about 250 ms, timeout, let me run the isMainProgramRunning method, then wait some more?
Edit2:
I tried using MsgWaitForMultipleObjects, although in a somewhat different way than Leo suggested. This is the loop I used:
while(MsgWaitForMultipleObjects (0, NULL, true, 250, QS_ALLPOSTMESSAGE) != WAIT_FAILED)
{
if(PeekMessage(&msg, NULL, 0, 0, true))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(!isMainProgramRunning())
break;
}
Again I had the same problem with the Sleep. I also tried suspending the main thread and having the other thread resume it. Same problem. What is it that GetMessage does that allows it to wait without causing these problems? Maybe this should be the subject of another post, but why is it that when the C++ application installing the hooks sleeps or is suspended, all processing in the hooks seems to suspend as well?
Edit3:
Here is the DLL method that the C++ application calls to install the hooks:
extern "C" __declspec(dllexport) void install()
{
cbtHook = SetWindowsHookEx(WH_CBT, hookWindowEvents, hinst, NULL);
if(cbtHook == NULL)
MessageBox(NULL, "Unable to install CBT hook", "Error!", MB_OK);
keyHook = SetWindowsHookEx(WH_KEYBOARD, LowLevelKeyboardProc, hinst, NULL);
if(keyHook == NULL)
MessageBox(NULL, "Unable to install key hook", "Error!", MB_OK);
}
You have two separate problems:
How to make the windowless C++ program exit automatically if the C# program exits (e.g. crashes).
In the C++ program, open a handle to the C# program. Since the C# program runs the C++ program, have the C# program pass its own PID as an argument; the C++ program can then open a handle to that process using OpenProcess.
Then use MsgWaitForMultipleObjects in your message loop. If the C# program exits the handle you have to it will be signalled and you will wake up. (You can also use WaitForSingleObject(hProcess,0)==WAIT_OBJECT_0 to check if the process is signalled or not, e.g. to verify why you were woken up, although the MsgWaitForMultipleObjects result will tell you that as well.)
You should close the process handle as you are exiting (although the OS will do it for you when you exit, it's good practice in case you re-use this code in a different context). Note that the handle outlives the process it represents, and that is why you can wait on it.
How to make the C# program instruct the C++ program to exit.
You may not need this if you get #1 working, but you could just have the C# program post a message to the C++ one if you want.
Do NOT use PostQuitMessage and do NOT post or send WM_QUIT across threads or processes.
Instead, post some other message that the two apps agree on (e.g. WM_APP+1) using PostThreadMessage.
You can create a named event and use:
MsgWaitForMultipleObjects
in your message loop.
The C# application only have to open and raise this event to tell your application to exit.
It's kind of minimal interprocess communication.
You should exit the process by posting a WM_QUIT message to it and handling it correctly, as specified in this article (Modality), by Raymond Chen. Don't sleep inside a loop without handling messages - it's wrong. Your app should either be handling a message or waiting for new messages.
GetMessage never returns is because you don't have a window created!
To use a message-queue you have to have some GUI. You Can for instance create a hidden window.

If MessageBox()/related are synchronous, why doesn't my message loop freeze?

Why is it that if I call a seemingly synchronous Windows function like MessageBox() inside of my message loop, the loop itself doesn't freeze as if I called Sleep() (or a similar function) instead? To illustrate my point, take the following skeletal WndProc:
int counter = 0;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
SetTimer(hwnd, 1, 1000, NULL); //start a 1 second timer
break;
case WM_PAINT:
// paint/display counter variable onto window
break;
case WM_TIMER: //occurs every second
counter++;
InvalidateRect(hwnd, NULL, TRUE); //force window to repaint itself
break;
case WM_LBUTTONDOWN: //someone clicks the window
MessageBox(hwnd, "", "", 0);
MessageBeep(MB_OK); //play a sound after MessageBox returns
break;
//default ....
}
return 0;
}
In the above example, the program's main function is to run a timer and display the counter's value every second. However, if the user clicks on our window, the program displays a message box and then beeps after the box is closed.
Here's where it gets interesting: we can tell MessageBox() is a synchronous function because MessageBeep() doesn't execute until the message box is closed. However, the timer keeps running, and the window is repainted every second even while the message box is displayed. So while MessageBox() is apparently a blocking function call, other messages (WM_TIMER/WM_PAINT) can still be processed. That's fine, except if I substitute MessageBox for another blocking call like Sleep()
case WM_LBUTTONDOWN:
Sleep(10000); //wait 10 seconds
MessageBeep(MB_OK);
break;
This blocks my application entirely, and no message processing occurs for the 10 seconds (WM_TIMER/WM_PAINT aren't processed, the counter doesn't update, program 'freezes', etc). So why is it that MessageBox() allows message processing to continue while Sleep() doesn't? Given that my application is single-threaded, what is it that MessageBox() does to allow this functionality? Does the system 'replicate' my application thread, so that way it can finish the WM_LBUTTONDOWN code once MessageBox() is done, while still allowing the original thread to process other messages in the interim? (that was my uneducated guess)
Thanks in advance
The MessageBox() and similar Windows API functions are not blocking the execution, like an IO operation or mutexing would do. The MessageBox() function creates a dialog box usually with an OK button - so you'd expect automatic handling of the window messages related to the message box. This is implemented with its own message loop: no new thread is created, but your application remains responsive, because selected messages (like for painting) are handled calling recursively your WndProc() function, while other messages are not transmitted, because of the modal type of the created window.
Sleep() and other functions (when called directly from your WndProc() handling a window message) would actually block the execution of your single threaded message loop - no other message would be processed.
MessageBox runs its own Win32 message loop (so as not to freeze calling app).
Beware of using it in non reentrant functions...
EDIT: to elaborate:
Message loop on windows is something like that (stolen from msdn):
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
DispatchMessage will call whatever window procedure it needs to. That window proc can start its own loop (on the same thread), and it will call DispatchMessage itself, which will call whatever message handlers.
If you want to see it, launch your app in debugger, pop up message box and break. You will be dropped somewhere within its loop. Look at the callstack and see if you can find parent loop.