HOWTO: Troubleshoot ActiveX Control Crashes in Internet Explorer

ID: Q247845


The information in this article applies to:
  • Microsoft Internet Explorer (Programming) versions 4.0, 4.01, 4.01 SP1, 4.01 SP2, 5, 5.0dp1, 5_beta


SUMMARY

Occasionally while using an ActiveX control (either one you developed yourself or a third-party control) inside an HTML page, Internet Explorer suffers a General Protection Fault (GPF), either midway through execution or while shutting down the browser. There are several known issues that can cause this to occur:

  • Your control is single threaded.
  • Your control hosts many other nested controls, each with its own window (hWnd) (Windows 95 and Windows 98 only).
  • Your control is not cleaning up resources properly.


MORE INFORMATION

Your Control is Single Threaded

Beginning with version 4.0, Internet Explorer requires that all ActiveX controls it hosts be apartment-threaded. Apartment threading is a concept from COM; it means that each control exists within its own protected execution context, or apartment. Internet Explorer requires controls to use at least a Single-Threaded Apartment (STA), in which all threads except the control's creating thread can access the control only by posting messages. STAs make it easy to add concurrency to your ActiveX control with little programmatic overhead.

Non-apartment threaded controls exhibit uneven behavior between different instances of Internet Explorer. On some machines, the control may appear to work fine; on others, its performance slows to a crawl; and on others, it crashes.

To check whether or not a control is apartment threaded, consult the Registry entry for the control, and look for the ThreadingModel value underneath the InprocServer32 key:

HKEY_CLASSES_ROOT\CLSID\{Your Control's CLSID}\InprocServer32\ThreadingModel 
This value should be set equal to Apartment. (It may also be set to Free or Both, which are also valid values. However, a control that declares itself free-threaded can be accessed by multiple threads simultaneously, and must safeguard access to its internal data through the use of critical sections. Failure to do this properly results in data corruption, which could result in a browser crash.)

If ThreadingModel is not set, your control is single-threaded. Fortunately, converting your custom control to apartment threading is an easy change. Consult the topic "apartment-model threading" in the MSDN Library for more information. If you are using a third-party component, you cannot just change this registry setting and expect the control to work; you must get a new version of the control from your component vendor.
For additional information on COM threading models, click the article number below to view the article in the Microsoft Knowledge Base:
Q150777 INFO: Descriptions and Workings of OLE Threading Models

Your Control Hosts Many Other Nested Controls

Tools like Visual Basic make it easy to create complex ActiveX controls that contain other controls to multiple levels of embedding. It is not uncommon to see a developer create a Visual Basic UserControl with dozens of constituent controls and an embedding hierarchy of seven or eight levels. However, such controls appear to perform worse on Windows 95 and Windows 98 systems as time goes on, generally causing the browser to crash after about 30 minutes to an hour of dedicated use.

In this case, your control is using up too many system resources, particularly window handles. Windows 95 and Windows 98 have a limited amount of space for window handles, which are stored in a heap contained in the USER32 library. This heap's size is dynamic on Windows NT, but limited to 32K per process on Windows 95 and 98. Excessive window handles, combined with a failure to clean up control resources properly (see below), can quickly exhaust Internet Explorer's window handle limit. One quick way to solve this problem is to make your controls windowless. Windowless controls save time and resources by forsaking ownership of a window handle; in this case, the control's container handles message-passing for the control through a set of OLE interfaces. Making controls windowless in Visual Basic, and in Visual C++ frameworks like Active Template Library (ATL), is very simple. See "Windowless Controls" in the MSDN Library for the details. For more information on the architecture of windowless controls, and what containers must do to support them, see the OLE Controls 96 specification.

Developers should also re-evaluate their control's design at this point. Such mammoth controls are hard to maintain and debug, and developers would best be served by breaking these giant control into several separate controls.

Your control is Not Cleaning Up Resources Properly

The more you use complex components (components that contain n other components), the more likely you are to create circular references. A circular reference occurs when Control A contains Control B, and Control B also has a reference back to Control A (say, via a Parent property). In this case, neither object is destroyed, and thus the DLL containing your control is never be unloaded. It will continue to consume more and more operating system memory, possibly destabilizing the entire computer.

This is another compelling argument for keeping the design of your controls flat and simple. In a control with more than four levels of containment, circular references are hard to track down, requiring tons of manual code instrumentation and debugging over several days. If breaking up the control is impossible, formulate a rigorous testing strategy, and verify the safety of each complex component--starting with the simplest controls and working up--before building on top of them.

Additional query words:

Keywords : kbActiveX kbIE400 kbIE401 kbIE500dp1 kbIE500
Version : WINDOWS:4.0,4.01,4.01 SP1,4.01 SP2,5,5.0dp1,5_beta
Platform : WINDOWS
Issue type : kbhowto


Last Reviewed: January 12, 2000
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.