Thu, 05 May 2005

Multithreaded Programming w/ Delphi 5 on Windows XP

I have successfully solved a very nasty little programming problem which only appears to show up under Windows XP. First, a little backround: At my work, we provide loan calculation libraries to other parties, for use in their systems. One of our potential customers requested that we prove that our 32-bit Windows library is thread safe.

I knew that the library (written in Delphi 5) was currently not thread safe (it wasn't written by me!), but estimated that I could get it up to snuff in about a day or two. Before 'fixing' the library, I set out first of all to write a multithreaded client to prove that it was not thread safe. That way, I could then fix the DLL and then re-run the tests, hopefully proving that what was once broken was now fixed, etc.

Delphi is a great language to program in. It is object oriented, with full support for all the OOP buzzwords like: polymorphism, information hiding, etc. Couple that with a great support library and a lightning quick compiler, and you have a very great combination. So, I quickly whipped up an application that spawns 4 worker threads, each of which compute a different loan 4000 times. Each time through the calculation loop, it checks to see if the results returned from the thread-unsafe library have changed from the correct, base line results computed in a single thread at application initialization.

As expected, the app crashes hard with EInvalidPointer exceptions, etc. It is ugly indeed. So, I then go into the DLL and strategically place some critical sections to protect the vulnerable areas, and then run the multithreaded test again. And it still doesn't work. However, it DOES work on Windows boxes of the flavors 98 and 2000. Very odd.

It is hear that my 40 days in the programming wilderness begins. I write a second, simpler console based multithreaded client in the thoughts that perhaps the vcl thread was creating problems. That didn't do the trick. I simplified the test apps as much as possible, with no luck.

After three days of pounding my head against this programming brick wall, scouring the net via Google, I stumbled upon a reference to a global variable names IsMultiThread, supposedly set up by Delphi in System.pas. This variable is supposed to be automatically set to true whenever you use Delphi's TThread object, and one would guess that it should also be set for DLL projects. I decided to explicitly set this variable to True in the initialization section of the DLL, as well as in the test applications startup.

EUREKA! The problem was solved, and I was able to rest over the weekend. Except that 2 out of 3 kids were sick, but that is an entirely different saga. So, the moral of the story is that when writing a multithreaded library or application in Delphi 5, just go ahead and explicitly set IsMultiThread := true. I hope this post can help someone avoid the same problem again!

posted at: 11:42 | path: /computers/programming | permanent link to this entry