Tuesday, August 17, 2010

Track memory leak using Purify

Tracking memory leak from a child process of a window service requires a little bit setup upfront.

I worked on a defect regarding to memory leak from a child process of a window service recently. I used the following steps to allow Purify to track the memory usage in the child process.

1. Add the Purify product directory and the Purify cache directory to the system Path environment variable. For a system service, it is important to add these directories to the system Path environment variable, not just the user Path environment variable.

2. Instrument both window service and child process executable from the command line.
purify /run=no /replace=yes win_service.exe
purify /run=no /replace=yes child_process.exe

3. Add ServicesPipeTimeout registry entry to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control with a big DWORD value, i.e. 180000 (3 minutes) to allow instrumented service to start from the Service Control Panel.

4. Select the option Allow Service to Interact with Desktop for the service so that Purify is visible while the service is running.

5. Change the service startup type to Manual.

6. Launch the instrumented service application from the Service Control Panel. When the service runs, it brings up Purify so I could see data for both the service and child process displayed in separate error views.

Friday, August 6, 2010

A lost and found exception

These days, I am working on a defect related to a lost exception due to a catch-all handler as following,

try
{
    do_something();
}
catch (...)
{
    log_message();
}

From the log message, it indicates that some exception has been caught in the catch-all handler. However, I do not have any exception specific information, such as exception code and type. Without any exception specific information, it would be impossible to figure out the cause of the exception.

Then I think whether it is possible to intercept an exception before a handler handles it. On Windows, there is a run-time API to translate a Win32 exception to a C++ typed exception before a C++ exception handler handles it.

_se_translator_function _set_se_translator(_se_translator_function seTransFunction);

typedef void (*_se_translator_function)(unsigned int, struct _EXCEPTION_POINTERS *).

Before a Win32 exception is handled by a C++ catch handler, including a catch-all handler, _set_se_translator intercepts the Win32 exception and then process it based on the _se_translator_function provided.

So I change the code as following,

void new_trans_func( unsigned int uCode, EXCEPTION_POINTERS* pExp )
{
    // process the exception based on uCode and pExp
}

try
{
    _se_translator_function old_trans_func = _set_se_translator(new_trans_func);
    do_something();
    _set_se_translator(old_trans_func);
}
catch (...)
{
    log_message();
}

I enable /EHa, recompile the code, and set a breakpoint in new_trans_func. When the breakpoint is hit, I dump the exception code and record.

After knowing what exception has been thrown, I enable the debugger to break on the exception before it is handled by any exception handler.