This process has been debugged...

Am Ende eines Prozesses kann einen Oops-Eintrag („This process has been debugged. If the debugger is Microfocus Anim2Wg, an inadvertent stop may have occured.“) erscheinen, der besagt, daß das beendete Prozess durch Debugging-Funktionen überwacht wurde. Falls der betroffene Debugger der Animator von Microfocus war, und das verfolgte Prozess vorzeitig beendet wurde, will diese Meldung zum Ausdruck bringen, dass hier noch längst keinen tatsächlichen Absturz vorliegt. Es ist denkbar, daß der Absturz verursacht wurde durch eine Fehlnutzung des sog. Exception-Handlings, wozu folgende Korrespondenz (vom 27.05.1997) näher Aufschluss gibt:


Die Grenze dessen, wo wir um andere Fehler herumprogrammieren können, ist im Falle des Cobol Animators anim2wg erreicht. Zunächst mal eine Aufstellung der Tatsachen:

  1. bietet die Möglichkeit, mittels der API WaitForDebugEvent für einen bestimmten Prozess das Auftreten bestimmter Ereignisse, wie das Laden einer DLL oder das Aufwerfen eines Ausnahmezustands (Exception), zu überwachen. Wenn eine Exception aufgeworfen wird, kann diese Exception von einem vorher hierzu installierten und registrierten Exception-Handler behandelt werden (klingt irgendwie vertraut, nicht?). Der Prozess, der einen anderen Prozess mittels WaitForDebugEvent überwacht, wird über den aufgeworfenen Ausnahmezustand grundsätzlich unterrichtet, bevor der installierte Exception-Handler diesen Ausnahmezustand erhält. Diese Tatsache wird in der sog. dwFirstChance Eigenschaft der Benachrichtigung vermerkt. Anschließend soll der überwachende Prozess dem überwachten Prozess die Fortsetzung gestatten, damit der Kernel den registrierten Exception-Handler für diese Exception anstoßen kann. Sollte für diese Exception jedoch kein Handler installiert worden sein, erhält der überwachende Prozess erneut eine Benachrichtigung über diesen Ausnahmezustand, diesmal jedoch mit der Eigenschaft dwFirstChance auf Null gesetzt. An dieser Stelle kann der überwachende Prozess noch irgendwelche Post-Mortem Dumps o.ä. ziehen, und den von ihm überwachten Prozess beenden. Andernfalls wird der Kernel den Prozess selber beenden, und dies mit einer Systemmeldung wie „Unhandled exception …“ melden.
  2. Der Microfocus Cobol-Animator anim2wg reagiert anscheinend bereits bei der ersten Benachrichtigung über einen aufgeworfenen Ausnahmezustand, als wäre es nicht eine sog. „First-Chance“-Nachricht, sondern die über eine „Unhandled exception“. Allerdings geschieht dies nur, wenn anim2wg einen NT-Prozeß überwacht. Beim Animieren eines .int-Codes wird kein NT-Prozeß überwacht, sondern lediglich ein Zwischencode interpretiert. Erst wenn anim2wg eine .exe debugged, was erst durch Setzen der Umgebungsvariable COBANIM_2 auf den Wert animate ermöglicht wird, startet anim2wg einen zweiten Prozess für die zu überwachende Ausführung, und verhält sich beim Auftreten eines Ausnahmezustandes von vornherein, als wäre dies ein nicht behandelter Ausnahmezustand, wodurch installierte Exception-Handler gar nicht mehr ausgeführt werden, sondern der Prozess beendet wird und somit effektiv das Standard Exception-Handling nicht benutzt werden kann.
  3. Bereits seit Windows 3.1 werden diverse API-Routinen geboten, die es ermöglichen, vor der Nutzung eines Pointers zu überprüfen, ob dieser Pointer eine gültige Adresse darstellt. Dazu benutzt der Kernel von Windows das Standard-Exception-Handling. Vorher installiert und registriert der Kernel einen Exception-Handler, um bei einem fehlgeschlagenen Versuch, die ihm übergebene Adresse auf die zu prüfende Art und Weise zu nutzen, dem Aufrufer einen booleischen Wert über die Gültigkeit der Adresse zurückreichen zu können. Die hier gemeinte API-Routinen sind IsBadReadPtr, IsBadWritePtr, IsBadCodePtr, IsBadStringPtr, IsBadHugeWritePtr und IsBadHugeReadPtr.
  4. An 202 Stellen in der TAA-Infrastruktur werden Argumente auf Gültigkeit der Adresse und des Speichers mittels des beschriebenen Exception-Handlings über die Kernel API Routinen überwacht. An 1.128 Stellen werden Handles von TAA-Objekten auf Gültigkeit überprüft, ebenfalls mittels des beschriebenen Verfahrens, von denen schätzungsweise 3% nicht so sehr die Korrektheit des Handles überprüfen, sondern über diesen Weg vielmehr feststellen, ob der angegebene Handle im eigenen oder in einem fremden Prozesskontext aufzufinden ist.
  5. Wenn die Funktionalität des Cobol Animators, Prozesse zu debuggen, benutzt wird, muss in der TAA-Infrastruktur auf der Nutzung der angegebenen Windows API verzichtet werden, um zu verhindern, dass anim2wg einen eigentlich korrekt ablaufenden Prozess beendet. An den 202 erwähnten Stellen, wo Adressen und Speicher auf Gültigkeit überprüft werden, lässt sich mittels einer Laufzeitabfrage, ob der aktuelle Prozess von einem Debugger überwacht wird, die Überprüfung reduzieren auf eine Abfrage, ob die zu prüfende Adresse NULL ist. Dadurch wird zwar einiges an Überwachung und Sicherheit genommen, aber im Fehlerfalle ist ja ohnehin der Debugger direkt präsent, um die Problemstelle anzuzeigen. Diese Änderung wurde bereits an der TAA-Infrastruktur vorgenommen. Die 1.128 Stellen, die Handles überprüfen, müssen jedoch genauer analysiert werden, ob hier versucht wird festzustellen, ob ein vermeintlich gültiger Handle in der Tat (noch) gültig ist, in welchem Fall eine ähnliche lockere Unsicherheit akzeptiert werden könnte wie bei den vorher erwähnten 202 Speicherüberprüfungen, oder ob an der jeweiligen Stelle in Wirklichkeit versucht wird festzustellen, ob der zu prüfende Handle im aktuellen Prozesskontext ungültig, in einem anderen jedoch gültig ist, und deswegen aus dem anderen Kontext gecloned werden muss. Wenn diese Funktionalität jetzt ohne das Standard Exception-Handling realisiert werden muss (ein Verzicht auf die Prüfung oder das lockere Übersehen einer solchen Konstellation ist in diesem Fall selbstverständlich nicht möglich), bedeutet das eine teilweise erhebliche strukturelle Umstellung der Infrastruktur. Schon nur die Analyse der 1.128 Stellen dürfte ein erhebliches Zeitfenster fordern (bei einem Schnitt von etwa 3 Minuten pro Stelle, sind das bereits 1,5 Personenwochen, wobei dann noch nichts umgebaut, sondern nur die Notwendigkeit für strukturelle Umbauten erkannt wurde).

Schlussfolgerung: Die Nutzung von anim2wg zum Debuggen von Prozessen ist sofort dann nicht möglich, wenn unterhalb solcher Prozesse standard Exception-Handling benutzt wird. Ein Umbau der TAA-Infrastruktur zur Umgehung dieser funktionalen Einschränkung im anim2wg stellt m.E. einen zu großen Aufwand zu diesem Zeitpunkt dar. Außerdem wäre dann immer noch nicht sichergestellt, dass in anderen Komponenten (z.B. ODBC) nicht auch mit Standard Exception-Handling gearbeitet wird, wodurch der TAA-Umbau nur einen Teil des Problems lösen würde. Nur dann, wenn anim2wg zum Debuggen von .int-Code benutzt wird, kann unterhalb des Animators Standard Exception-Handling verwendet werden. Achtung: auch beim Debuggen von .int-Code treten die o.g. Probleme auf, wenn die Umgebungsvariable COBANIM_2 auf den Wert animate gesetzt wurde!