After a long odyssey I finally found a solution for fixing a problem in our Delphi project that caused from time to time some unexpected and hard to trace crashes during the startup phase of our software on a Terminal Server (in a RDP session). The software crashed about 1 out of 20 starts and it took us almost 2 years to understand and find the source of the problem.

After a long odyssey I finally found a solution for fixing a problem in our Delphi project that caused from time to time some unexpected and hard to trace crashes during the startup phase of our software on a Terminal Server (in a RDP session). The software crashed about 1 out of 20 starts and it took us almost 2 years to understand and find the source of the problem.

Keeping this story short ...

The final solution was to add the following line to the dpr files in our project:

{$SETPEOPTFLAGS IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE}

As I understand this case: If this flag is missing, the terminal server produces some "hick ups" in the initialization process of a program within a RDP session due to some mix up of DLL initialization that happens only during a RDP session.

My question is now: Is there any good reason NOT to add this line to any project? What are the possible side effects?
Via Google I found only sources explaining how to add this /TSAWARE flag to a Delphi project but didn't find any further background information why it must be added and why this isn't the default for any software.

Comments

  1. I'd love to hear more about this. I've had random reports of problems in Terminal-Service for my app, but I wasn't appear it dealt with apps differently. Would also like to hear any thoughts on this...

    ReplyDelete
  2. Is it related to shared memory or use of signaling? Any COM involved?

    ReplyDelete
  3. Roland Bengtsson Yes, found this article before but it didn't help to understand our problem. We don't use INI files or the registry in the way the article describes. Other sources mention a difference in DLL initialization in a Terminal Server environment.
    Lars Fosdal No, due to the required stability of our software we reduced the dependence on external DLLs and shared resources to a minimum. The only DLLs left are the database engine that connects to the database server. From the pure technical view our software is quite simple - it could be run from a USB stick on fresh installed Windows.

    While searching the cause of the crashes we found several things that showed us a link to Terminal Server. Changing the color depth in the RDP client changed the percentage of crashes; dis/allowing access to client printers and drives changed the percentage of crashes as well. The event log on the server always showed problems in DLLs that are somehow related to the Terminal Server operation. But there was still no way to reproduce the crashes. Testing it on our own terminal servers didn't show any crashes at all while customers who connected to our own test server have been able to experience the crashes - we logged in with the customers credentials - no crash.

    After a long time we have been able to limit the crashes and related entries in the event log to problems in the mswsocks.dll. So we changed the database engine DLLs to a newer version, upgraded the database server itself to a newer version. In result the number of crashes decreased but didn't disappear completely.

    Some days ago I searched in Google for "Delphi mswsocks.dll Remote Desktop" and the first result shown was this article: http://support.microsoft.com/kb/2279689 That's the only reliable source so far that mentions the different way of DLL initialization on a Terminal Server. From there it was only a small step to find a Delphi related post suggesting the inclusion of {$SETPEOPTFLAGS IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE} in the project file.

    So, now we have this included in all related project files and the crashes on Terminal Server fully disappeared. Odyssey finished.

    Now I wonder if there is any good reason not to include this compiler switch in all our projects? Shouldn't this be the normal default setting in all Delphi applications?

    ReplyDelete
  4. I must thank you that you made me aware if this flag. Our 10 year old application is executed with Citrix. When I tried the flag it cuts the startup-time with several seconds. So the difference is only that your application cannot modify Windows-folder or the registry. So for most applications it should be safe to use it.

    ReplyDelete
  5. Fred Ahrens - That's a good question.  You did however mention that you made several changes to improve the app under TS, and those changes are probably still relevant.  If you flag another app as TS Aware, shouldn't it also have had the same measures applied?

    ReplyDelete
  6. Lars Fosdal There are of course many other things to consider if you want to make your executable terminal server compliant. But all this has been applied already long time ago and is part of our best practice. All other changes applied to the RDP client and our software while trying to find the source of the crashes are finally no longer relevant as the missing TSAWARE flag was the actual source of the problem. Applying the TSAWARE flag to a 3 year old version of our software solved the problem there as well. So we are on the safe side to assume that everything else applied recently isn't part of the solution for this problem. Of course - with software it's never 100% safe to make such assumptions :)

    ReplyDelete

Post a Comment