My program launches a thread (in the WM_CREATE) handler.

When this thread exits naturally, if it changes the value of ebp before exitting, then the program terminates, without apparently processing WM_CLOSE or WM_DESTROY. If on the other hand the thread ends with ebp intact, the program waits for closure (click the x) and exits with WM_CLOSE and WM_DESTROY.

Why does this happen please?

Also, does exitting a thread automatically give any signal to the main program? Or does one need to send the message in another way? Thanks.
Posted on 2005-11-13 22:24:47 by V Coder
Register preservation rules, mate - EBX,ESI,EDI,EBP must be preserved in callbacks (including threads). When you "RET" from a thread, you go back to some OS cleanup code, which likely depends on local variables accessed through EBP.

Also, if you use a standard PROC in masm, not preserving EBP well mess up your stack when doing RET; if ESP is not inside the range defined in the TEB, windows will terminate your prorgram silently.

Exiting a thread doesn't automatically send any signal to the main app (it does to DLLs though). When you create a thread, though, the return value is a HANDLE that you can wait on (WaitForSingleObject() or one of the other wait functions). You should always remember to call CloseHandle() on this value when you're done with it (if, if you don't WaitFor*Object, CloseHandle() right away).
Posted on 2005-11-14 00:47:22 by f0dder
To add to f0dder's post, this is what a default prelude looks like:

push ebp
mov ebp, esp
sub esp, size_of_locals

And the default epilogue:

mov esp, ebp
pop ebp
retn number_of_arguments

Where "size_of_locals" and "number_of_arguments" are placeholders for the actual values. These are added automatically by MASM to each of your procedures. This is how local variables are accessed:

mov eax,

Where again "offset_to_local" is a placeholder.

So trashing EBP causes two effects: one, the procedure will try to access it's local variables from the wrong places, most likely crashing your app; two, the epilogue will try to restore ESP from the value of EBP, now the thread is trying to access it's whole stack at the wrong place. The latter makes your program crash so bad that Windows can't even show an error message, and your app dies silently.
Posted on 2005-11-14 09:21:31 by QvasiModo
My WM_COMMAND launches the active thread of my program, which launches a second thread if a hyper-threading CPU is present. Can thread2 terminate after thread1, will that cause problems? How should I preserve registers? With pusha at the start and popa at the end, or should I just use temporary variables for ebp, esi, edi, ebx?

Posted on 2006-01-09 20:48:05 by V Coder
Just push the value of the register you want to preserve onto the stack, then pop it to preserve the value. Like for example if you are messing around with ebp, you can do

push ebp
mov ebp,1
pop ebp
Posted on 2006-01-09 22:28:50 by roticv
Can thread2 terminate after thread1, will that cause problems?

it can, unless you call ExitProcess in the main thread :P. For me it looks this way: 1st thread has its work done and it
calls ExitThread, when the 2nd thread's work is done it(2nd thread) calls ExitProcess which will do most of the needed cleanup.
Posted on 2006-01-10 06:22:02 by k3Eahn
Okay, once the thread terminates, the program can start another thread if it wants.

How do I make the WinProc detect when either or both threads is terminated please so as to reenable the appropriate menu items. Thanks.
Posted on 2006-01-10 06:36:30 by V Coder

GetExitCodeThread will quickly tell you if a thread is still running or not.
Posted on 2006-01-10 08:02:14 by japheth
Rather than polling GetExitCodeThread, you could have your threads send messages to your winproc when they exit.
Posted on 2006-01-10 09:57:46 by f0dder
Or you call WaitForMultipleObjects and pass it the thread handles. But I prefer the message queue solution.
Posted on 2006-01-10 10:45:45 by QvasiModo
Yeah, WFMO isn't very suitable if he needs the WndProc to handle thread creation and menu (re)-enabling :)
Posted on 2006-01-10 14:28:23 by f0dder
Thanks I was also thinking about using PostMessage.
Posted on 2006-01-10 19:37:53 by V Coder