Solved

Exception Handling in Windows Message Loop

Posted on 2006-10-29
4
1,836 Views
Last Modified: 2012-06-27
We have found something interesting out with an win32 C/C++ application (vc6 & vc8)and the message pump handling (in this case WM_TIMER).

A 3rd party dll could cause an exception without exception protection without the application crashing. In our case this was bad because the state of internal code became indeterminate because the DLL entry point did not have an exit point, i.e. the WM_TIMER called a function which crashed, then just called it again on the next timer.

Some sample code will follow which shows this behaviour :

>> The question is does anyone know of something definitive on why this behaviour is happening ? Under MSDN and elsewhere, we can't find any doco on message loop handling that references that it protects the function call from crashes .

To ensure that the call is "stateful" we will need to try / catch many code points within the WM_TIMER function .

Sample code :


#include "stdio.h"
#include "windows.h"
#include "resource.h"


//Timer callback function
void CALLBACK RecvTimer(HWND hwnd, UINT msg, UINT idTimer, DWORD dwTime)
{
      char *test = NULL;
      *test = 'a'; //Throw SEH exception (access violation)
}

//Initilise the timer
bool InitTimer()
{
      return SetTimer(NULL, 1199, 100, (TIMERPROC)RecvTimer);
}

void main( int argc, char** argv )
{
    // create the dialog window
    HWND hWnd = ::CreateDialog(NULL,
        MAKEINTRESOURCE(IDD_DIALOG),NULL,NULL);

    if ( hWnd!=NULL )
    {
        // show dialog
        ShowWindow(hWnd,SW_SHOW);
    }
    else
    {
        printf("Failed to create dialog\n");
        exit(1);
    }

      //Initilise the timer.
      if (!InitTimer())
      {
            printf("Failed to initilise timer\n");
            exit(1);
      }
    // message loop to process user input
    MSG msg;
    while (GetMessage(&msg, // message structure
            NULL,           // handle to window to receive the message
            NULL,           // lowest message to examine
            NULL)          // highest message to examine
           != 0 && GetMessage(&msg, NULL, NULL, NULL) != -1)
    {
 
        // Post WM_TIMER messages to the hwndTimer procedure.
 
        if (msg.message == WM_TIMER)
        {
            msg.hwnd = hWnd;
        }
 
        TranslateMessage(&msg); // translates virtual-key codes
        DispatchMessage(&msg);  // dispatches message to window
    }
}

/************************** end ************************/
0
Comment
Question by:greg_roberts
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
4 Comments
 
LVL 11

Expert Comment

by:DeepuAbrahamK
ID: 17834353
RecvTimer() is the callback function which user has written and is nothing to do with the message loop. What message loop will do is, it will just call the callback funtion which we have already registerd in the SetTimer function.Also modified your code to catch the exception properly.

Hope it helps!,
Best Regards,
DeepuAbrahamK
//---------------------8<---------------------------------------------8<------------------//
#include "stdio.h"
#include "windows.h"
#include "resource.h"

//Timer callback function
void CALLBACK RecvTimer(HWND hwnd, UINT msg, UINT idTimer, DWORD dwTime)
{
      try
      {
            char *test = NULL;
            *test = 'a'; //Throw SEH exception (access violation)
      }
      catch(...)
      {
            printf("Exception !!");
            PostMessage(hwnd,WM_DESTROY,0,0);
      }
}

//Initilise the timer
bool InitTimer()
{
     return SetTimer(NULL, 1199, 100, (TIMERPROC)RecvTimer);
}

void main( int argc, char** argv )
{
    // create the dialog window
    HWND hWnd = ::CreateDialog(NULL,
        MAKEINTRESOURCE(IDD_DIALOG),NULL,NULL);
      
    if ( hWnd!=NULL )
    {
        // show dialog
        ShowWindow(hWnd,SW_SHOW);
    }
    else
    {
        printf("Failed to create dialog\n");
        exit(1);
    }
      
      //Initilise the timer.
      if (!InitTimer())
      {
            printf("Failed to initilise timer\n");
            exit(1);
      }
    // message loop to process user input
    MSG msg;
    while (GetMessage(&msg, // message structure
            NULL,           // handle to window to receive the message
            NULL,           // lowest message to examine
            NULL)          // highest message to examine
            != 0 )
    {
            
        // Post WM_TIMER messages to the hwndTimer procedure.
            
        if (msg.message == WM_TIMER)
        {
            msg.hwnd = hWnd;
        }
            
            if (msg.message ==WM_DESTROY)
            {
                  // Destroy the timer.
                  KillTimer(msg.hwnd, 1199);
                  PostQuitMessage(WM_QUIT);
            }
            else
            {
                  
                  TranslateMessage(&msg); // translates virtual-key codes
                  DispatchMessage(&msg);  // dispatches message to window
            }
            
            
    }
}
//---------------------8<---------------------------------------------8<------------------//
0
 

Author Comment

by:greg_roberts
ID: 17838139
Thanks for your interest but what you suggest is what we know.

>> We are after definitive information on the why / how this DispatchMessage protection exists, as on paper there is no reference to it in the MSDN documentation .

Please refer to the >> question above.

PLEASE NOTE TO OTHER READERS, THE QUESTION HAS NOT BEEN ANSWERED
0
 
LVL 5

Accepted Solution

by:
NickGeorghiou earned 250 total points
ID: 17841004
Hi,

This article may not give you a definitive answer. But it does point out that VC++ exception handling can in fact default to the application continuing in an inconsistant state. One quote from this article which sounds relevant is:

 "For example, if a program is required to use a third-party library, and the library has bugs of this kind, and the developers have no access to the library source code, then..."  
"   ... it may be considered better for the program to limp along rather than die."

It also points out that compiler optimisation (if used) will may affect exception handling.

http://www.thunderguy.com/semicolon/2002/08/15/visual-c-exception-handling/

Hope this helps,
Regds,
Nick
0
 

Author Comment

by:greg_roberts
ID: 17847281

Thanks Nick

This article is probably the best on the Web.

It is a great shame that Microsoft don't have this whole area spelled out as it can have a profound affect on your application.

Personally we would prefer that the handling could be turned on/off so we get a clean crash, especially during testing and beta use.
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question