Fixing Rad Studio/Delphi RTL’s MakeObjectInstance()

Fixing Rad Studio/Delphi RTL’s MakeObjectInstance()

*Updated on Nov/2019

A few days ago, investigating some core issues reported by one of our IntraWeb customers, we found that there may be an issue with Delphi RTL’s function, MakeObjectInstance().

This function is declared in Classes.pas and it is used by all TWinControl descendants, called during object creation. The issue here is: MakeObjectInstance() is not thread safe. It uses a global list without any locking mechanism. If two or more threads are creating TWinControl descendants and both are calling MakeObjectInstance() at the same time… guess what? The global list may get corrupted and then any sort of malfunction may happen within your application. TFrame class, and also IntraWeb classes TIWForm and TIWRegion descend from TWinControl, so the issue may have impact on heavy loaded IntraWeb applications.

This issue is perfectly explained by Primoz Gabrijelcic (creator of Omni Thread Library) in his blog: http://www.thedelphigeek.com/2007/06/allocatehwnd-is-not-thread-safe.html

There is also a Quality Central report about that: http://qc.embarcadero.com/wc/qcmain.aspx?d=47559. Note that this QC dates from 2007, so this is not new.

Primoz Gabrijelcic’s post covers AllocateHwnd() but the root of the problem is the same: MakeObjectInstance() called simultaneously by different threads. This not only affects IntraWeb applications, but also any multi-threaded application where two or more threads may call MakeObjectInstance (TTimers in threads are another example, as pointed by Primoz).

So we created IWRtlFix to avoid problems with MakeObjectInstance() call. What does it do exactly?

First versions of IWRtlFix used a critical section to handle concurrent access which was pretty simple, but obviously has performance/scalability issues.

Current version of IWRtlFix uses an exclusive list per session which solves the problem elegantly, keeping maximum performance and no scalability impact.

How to use the fix:

  • Add IWRtlFix unit as the first unit (or second) in your project’s DPR file. If you are using another memory manager (FastMM, ScaleMM, etc), declare IWRtlFix as the second unit, right after the memory manager unit.
  • Rebuild it your project and you are done!

Further notes:

  • Due to copyright restrictions the tool will only create the IWRtlFix.pas file if you have Rad Studio / Delphi IDE and original Classes.pas installed on your machine.
  • The file created is compatible (and was tested) with all supported Rad Studio / Delphi versions from Delphi 2009.