Thread: Forcing MessageBox to be non-concurrent?

  1. #1
    jasondoucette.com JasonD's Avatar
    Join Date
    Mar 2003
    Posts
    278

    Forcing MessageBox to be non-concurrent?

    Hello,

    I have created a fatal error function that displays text passed to it via MessageBox, and then shuts down the application. I am having problems with MessageBox's tendency to be concurrent. Since the program flow continues after the message box is displayed, the application is shut down immediately, before the user has a chance to read the message, or click 'ok' to close it.

    If I grab the result returned back from MessageBox (and do something with it, so the compiler does not optimize the code out), then the program will wait for the message box to close, as the program flow cannot continue on without this piece of information.

    (EDIT: Since more than a few have been confused by the above, I am going to point out that the code that is 'optimized out' is NOT the function call, but the variable that stores the result of the function, which is not used for any other reason. The compiler knows that this variable is useless, and therefore does not even reserve space in memory for it. I hope this clears up my comment. )

    So, I have a few questions:
    1. Where is all of this documented? I cannot find any information from MSDN's documentation on MessageBox.
    2. Is it possible to force the program flow to wait for a message box to terminate without adding useless junk code (that may or may not be optimized out in some future, smarter version of my compiler)?
    3. Do you have any information that may help solve this problem of creating a proper fatal error function?

    Any help is appreciated.

  2. #2
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    I have never seen MessageBox() behave in this way. The function does not return until the box is closed.
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  3. #3
    jasondoucette.com JasonD's Avatar
    Join Date
    Mar 2003
    Posts
    278
    I forgot to mention one thing, which your reply reminded me of:

    Due to the OS independency of my code (I have a layer between the windows functions and the actual program for easier porting), a NULL is passed for the hWnd parameter to MessageBox, which is the handle to the owner window of the message box to be created. MSDN says that if this parameter is NULL, the message box has no owner window. The reason NULL is passed is simply because my OS independent layer has not been programmed to store and pass such information along to the OS specific layer. Seeing the extra difficulty in programming this, and no additional benefit for it, I simply forget about it. Thus, I pass NULL.

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    No compiler should ever "optimize out" a call to MessageBox(). And not waiting for a function to return isn't an "optimization" that non-parallelizing compilers are capable of.

    What compiler are you using?
    What is the last parameter you are passing to MessageBox()?
    Do you have a dialog box active when MessageBox() is called?
    How do you know that your MessageBox() calls are running asyncronously? What's your evidence and how was the evidence observed?

    gg

  5. #5
    jasondoucette.com JasonD's Avatar
    Join Date
    Mar 2003
    Posts
    278
    Codeplug, thank you for your reply. I should have been clearer. I will explain:

    The compiler will 'optimize out' a variable that exists only to store the result of MessageBox, if this variable is never used again (see code below). Therefore, you must do something with this variable, such as use it in an if-statement, so that it is not optimized out. In this case, the MessageBox call MUST end, and return the value before the code can continue, as it needs its value to determine which program path to flow through. In the case that the result of MessageBox is not needed (perhaps due to the fact that the variable to store its result is 'optimized out'), then the code will continue, NOT waiting for the user to close the message box.

    Please note that I am passing NULL for hWnd (the first parameter). I believe that MessageBox always waits if this is not the case.

    The compiler I am using is MSVC++ 6.0

    I pass MB_OK as the last parameter. I have tried passing MB_TASKMODAL to see if there is a difference. It appears to make no difference.

    I have a modeless dialog box active, and I have removed it. It appears to make no difference.

    My evidence is that the code is called like so:
    Code:
    int result = MessageBox (NULL, szMessage, szCaption, MB_OK | MB_TASKMODAL);
    
    //if (result == IDOK)
    	exit(1); // shut down after clean up
    The program terminates immediately upon calling the function with the above code, showing that it does not wait for the MessageBox() to return. If I uncomment out the if-statement, then its value is needed, and the program will wait for MessageBox to return.

    Apparently, I need to pass the window's handle to the MessageBox call. I will have to find a way to store this from the OS specific layer into my OS independent layer, which, in turn, will pass it back through. This is something I wanted to avoid, since it's ugly.

  6. #6
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    I think something else must be closing the app. MessageBox does not return until the box closes. To demonstrate this, use the debugger. Put a breakpoint on the line following the MessageBox call. You won't hit it until the box closes.
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  7. #7
    jasondoucette.com JasonD's Avatar
    Join Date
    Mar 2003
    Posts
    278
    Thanks for your reply.

    Something else I forgot... The message box is being called from a child window. I have confirmed that MessageBox does not return immediately, even if passing NULL as the window handle, if the main window is calling it.

    I do not believe anything else is closing the application, because if I comment out the call to my fatal error function (which just calls MessageBox and then exit), the program continues executing fine (it does not close down).

    I will do some further testing, and let you know what I find.

  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Check result for 0.
    This indicates that MessageBox() failed.
    Call GetLastError() if this is this case and use Tools->Error Lookup from the menu bar to find out what the error means.

    gg

  9. #9
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Hi.

    The compiler can not and will not ever optimize out a function call of which it does not know the contents. Also, it can not decide to continue before a function has finished. Think about the Sleep() function, when was the last time anyone used its return value?

    In general, I don't think any of us should be losing sleep over the compiler optimizing out code that we need.

    The MessageBox function pumps the message queue. This allows an application to continue receiving paint messages and input messages and generally stay responsive while the dialog is displayed.

    If there is a WM_DESTROY message in the queue it will be dispatched. A common response to WM_DESTROY is to call PostQuitMessage. Now if there is a WM_QUIT message in the queue, guess(you'll have to because it is not documented) what happens? The MessageBox function destroys the dialog and returns immediately.

    So, in your fatal error handler you might post WM_CLOSE to a window before calling MessageBox(), this turns into WM_DESTROY when it is dispatched from inside the MessageBox() function, MessageBox() returns immediately and your application terminates.

    If the message box is still visible, then only the window has been destroyed and your app is still running. The message box can not exist after the process has terminated.

    If I uncomment out the if-statement, then its value is needed, and the program will wait for MessageBox to return.

    That's probably because MessageBox() is not returning ID_OK and so the exit() statement is not executed!

    All this is poorly documented and there must be a lot of 'broken' apps out there that expect their windows to still exist after a call to MessageBox. If you need to use a window after a call to MessageBox you can protect your code with a call to IsWindow to make sure it is still alive.

    On a side note, you can find my XMsgBox code, which extends the MessageBox api to offer async operation, countdown and arbitary button captions, here(down the bottom).

  10. #10
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    I hadn't thought of this, but you're claiming this is in the "fatalerror" function. Is it possible that whatever the error was caused a memory overwrite or something?
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  11. #11
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    by the way, I really don't think the exit() function should be used in a windows app. Windows cleanup is poor to say the least. It's not like unix where closing a process frees all of the app memory.
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  12. #12
    jasondoucette.com JasonD's Avatar
    Join Date
    Mar 2003
    Posts
    278
    Thank you all for your replies. I know it is difficult without code to analyze this. I think I may have to write up a small app with a child window that replicates this, to see if there is not something else causing the problem. Normally, I am able to reduce all other possibilities even within a large program to narrow down the problem. I thought I had done this, thinking that MessageBox simply allows program flow to continue... I, apparently, was wrong.

    Codeplug, since the MessageBox appears when I comment out the exit call, I know that it is being drawn. Is it possible for the box to be drawn, and still result in 0 being returned? I will test for this...

    anonytmouse, thanks for your detailed reply.

    I will point out again that I did not mean to imply that the function call itself is 'optimized out', just the variable that stores its return value. I have edited my original post to hopefully make this clearer.

    Basically, my error routine follows alone these lines:

    From within a child window, there is a test for a fatal error. If this test fails, it calls a fatal error function, which in turn calls MessageBox to display some text, and then calls exit.

    I do not place a WM_DESTROY message in the queue before the MessageBox call. But perhaps something is happening behind the scenes that I am unaware of, since something is making the MessageBox disappear before the user presses 'ok'. I know that if the application gets a message to terminate, it will close the message box with it (i.e. it will not wait for the user to close it).

    When the exit() statement is not executed (if I comment it out), then the program does not terminate. This is how I am fairly sure nothing else is going on that I don't know about. The code in a previous post that has the exit call within an if-statement was just to show that an if-statement can force the compiler to make use of the return value from the MessageBox. I fear that I made the problem sound more complicated as a result. My actual function only calls MessageBox and exit, without any if-statements.

    FillYourBrain, the if-statement that calls the fatal error is checking to ensure there is proper memory for what comes next. If this fails, then the fatal error message is called. Even if program execution resumes after this fatal error function is called (i.e. if the function does not call exit, and merely calls MessageBox and then returns), the code does NOT follow through assuming there is sufficient memory. So I can properly test the code even when forcing the fatal error function to NOT quit.

    For those who are interested, the main problem is this: I have a child window which displays a bitmap. The bitmap's size is set to the size of the screen, assuming this is the largest the client area will ever be (and changed when resolution changes), yet, it checks to ensure that the client area size (of the child window) is NEVER larger than the bitmap itself, as the client area size is used to fill the bitmap with data, and then the bitmap is drawn to the child window. I found that a child window's size can actually be larger than that of the screen. I can solve this by simply not allowing it to become this big, BUT, for now, it just calls a fatal error function. This is the problem this thread speaks about. I dislike leaving something that I do not know the solution to, so I wish to solve it, even though I do not really need it.

  13. #13
    jasondoucette.com JasonD's Avatar
    Join Date
    Mar 2003
    Posts
    278
    Originally posted by FillYourBrain
    by the way, I really don't think the exit() function should be used in a windows app. Windows cleanup is poor to say the least. It's not like unix where closing a process frees all of the app memory.
    I was wondering this myself... I use it because I have seen it used in professional windows code in a fatal error function.

  14. #14
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    I'm not sure I understand still. Is the message box just flashing, does it not show at all? If you comment out the exit is the behaviour of the message box the same, or are you saying thatit then stays around? It sounds like you are saying that the problem is that the MessageBox function is failing. What does GetLastError return?

  15. #15
    jasondoucette.com JasonD's Avatar
    Join Date
    Mar 2003
    Posts
    278
    anonytmouse, here is the code:

    This is the child window's message handler that catches the fatal error (not exact code, but just cut down to show what's happening):
    Code:
    if ((xsize < cxClient) || (ysize < cyClient)) 
    {
    	SYS_FatalError(....);
    }
    This is the SYS_FatalError() function:
    Code:
    void SYS_FatalError(....)
    {
    	MessageBox(....);
    	exit(1);
    }
    If I comment out the exit, the message box appears (but it's window title is EMPTY... I have never seen this before - I do pass it something for the title). It returns 1 (IDOK), meaning that there is no error in calling it.

    If the exit is left as is, then I don't see the message box. As soon as the error occurs, the entire app closes. I assume the message box shows for a split second before terminating. This is what led me to believe that the execution continues after MessageBox is called.

    The difficulty is that the child's client area size (after being resized by the user) is what is causing the error. This is checked during re-draw, therefore this error continually happens, as windows knows the window has not been painted, and thus attempts to paint it. The size problem still exists while the fatal error message box is being displayed. But, only one message box is displayed at a time. Each successive error waits for the previous message box to terminate. Maybe this is the source of something happening behind the scenes that I do not know about. I will attempt to stop this behaviour, and let Windows think it has nothing to do after a first failed attempt at re-draw.

    I will let you know...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. MessageBox, changing text.
    By XunTric in forum Windows Programming
    Replies: 8
    Last Post: 01-16-2006, 09:09 AM
  2. Delete files that are used
    By Yuri in forum C++ Programming
    Replies: 8
    Last Post: 10-18-2005, 01:48 PM
  3. problem with A simple modeless messagebox
    By hanhao in forum C++ Programming
    Replies: 8
    Last Post: 07-05-2005, 11:18 PM
  4. EnterCriticalSection and MessageBox
    By novacain in forum Windows Programming
    Replies: 13
    Last Post: 01-30-2003, 08:48 AM
  5. double in a MessageBox
    By Robert602 in forum Windows Programming
    Replies: 3
    Last Post: 12-17-2001, 03:10 PM