Ende ohne Schrecken: William Kahan und der geordnete Rückzug von Computerprogrammen

1 October 2013 by Markus Pössel, posted in Computer Science, Deutscher Blog

In einem früheren Beitrag war ich mit William Kahan in die frühe Neuzeit der Computertechnik zurückgereist. Dabei hatte mir Kahan auch erzählt, wie er das erste Mal ein Software für eine Firma geschrieben habe - ein Programm nämlich, das Trans-Canada-Airlines (heute: Air Canada) dabei helfen sollte, Telegraphiekosten zu sparen, indem es Sitzplatzreservierungen auf diversen Flügen überwachte und koordinierte.

William Kahan während seines Vortrags beim #hlf13
©HLFF, Christian Flemming

Derjenige Teil des Programms, der sich direkt mit Sitzplätzen beschäftigte, sei dabei das geringste Problem gewesen. Knackpunkt war stattdessen, dass der Computer, auf dem das Programm lief, nur etwa 5 Minuten am Stück fehlerfrei operierte.

Die meiste Energie musste Kahan daher investieren, sicherzustellen, dass das Programm trotz diverser Mankos weiterlief: mit Checksummen, die sicherstellten, dass keine Information verloren gegangen oder verfälscht worden war, und mit Prozeduren, mit denen das Programm nach einer Unterbrechung die richtige Stelle zum Weitermachen finden konnte. So konnte das Programm ungleich länger als fünf Minuten laufen, ohne dass es zu Fehlverhalten kam.

Die Sicherheitsmaßnahmen waren also ein voller Erfolg. Kahan erinnert, dass nur eine einzige andere Person, Harvey Gellman, damals soviel Leistung aus dem Computer herausholen konnte, wenn der gerade seine Mucken hatte.

Gegeben diese Vorgeschichte ist es nicht überraschend, dass Kahan auch in seiner weiteren Karriere ein Auge darauf hatte, was mit Computerprogrammen alles schiefgehen kann. Er ist längst zu dem Schluss gekommen, dass wir mit solchen Problemen ganz allgemein nicht besonders gut umgehen. Was passiert denn, wenn ein Programm oder ein Programmteil irgendwelche unvorhergesehenen Probleme hat? Wenn ein Sensor Daten liefert, die nicht dem entsprechen, was der Programmierer erwartete? Wenn es unerwartete Fließkommaprobleme gibt? (Einige der Beispiele Kahans für höchst sonderbares Fließkommazahlen-Verhalten hatte ich ja bereits in Eingebaute Fehler: William Kahan und die Fließkommazahlen wiedergegeben.)

Falls sich nicht jemand die Mühe gemacht und Vorsorge getroffen hat - wie Kahan mit seinem Reservierungsprogramm - ist die ungeschriebene Konvention, dass das Programm beim Auftreten solcher Laufzeitfehler schlicht abgebrochen wird. In Zeiten der Stapelverarbeitung in den 1960er Jahren mag das sinnvoll gewesen sein - soll ein Programm nach dem anderen Laufen, dann bekommt, wenn ein Programm abstürzt, eben das nächste in der Schlange seine Chance. In Situationen, in denen Software komplexe Systeme steuert, kann ein solches Verhalten dagegen fatal sein. Es bedeutet letztlich, dass die Kontrolle vom Programm aus irgendwo anders hin übertragen wird - und es nicht klar, wie das System mit einem solchen abrupten Wechsel umgeht.

Was dann passiert, kann im schlimmsten Falle Leben kosten. Kahans markantestes Beispiel ist der Absturz des Flugs AF447 am 1. Juni 2009: Als die Geschwindigkeitssensoren des Flugzeugs ausfielen und entsprechend widersprüchliche Werte lieferten, machte der Autopilot genau das, was Kahan kritisiert: Das Programm wurde gestoppt und gab die Kontrolle einfach so ab. In diesem Falle an die menschlichen Piloten - aber ohne, dass den Piloten mitgeteilt wurde, was da eigentlich passiert war. Den Piloten blieb kaum Zeit, die Situation verstehen, denn kurz darauf kam es schon zum Strömungsabriss, und Minuten später schlug das Flugzeug auf der Meeresoberfläche auf und brach auseinander. Alle 288 Menschen an Bord starben.

Ein weiteres Beispiel? Die USS Yorktown. Übersetzt nach diesem Text (PDF) von Kahan:

Am 21. September 1997 befand sich die Yorktown in der Nähe von Cape Charles, Virginia, als ein Matrose aus Versehen ein leeres Feld in eine Datenbank eingab. Das Programm behandelte die Eingabe wie eine Null und brach ab - mit einem Fehler "Versuch, durch Null zu teilen". Das Datenbankprogramm konnte mit diesem Fehler nicht umgehen, stürzte ebenfalls ab und übergab die Kontrolle an das Betriebssystem, Microsoft Windows NT 4.0. Jenes stürzte ebenso ab und schaltete dabei alle Bildschirme und Terminals im ganzen Schiff aus.

Das Ergebnis: Ein ziemlich großes Kriegsschiff, auf dem fast 3 Stunden lang gar nichts mehr ging. Glücklicherweise befand sich das Schiff weder in einer Gefechtssituation noch in gefährlichen Gewässern.

Dann war da noch der misslungene Start einer Ariane 5 am 4. Juni 1996. Ein Teil des Navigationssystems, dessen Aufgabe es war, Geschwindigkeitsänderungen der Rakete zu verfolgen, bekam Werte, mit denen es nichts anfangen konnte, und stürzte daraufhin ganz ab. Die Rakete daraufhin auch.

Können die Programmierer nicht einfach berücksichtigen, was mit ihrem Programm schiefgehen kann - und ihre Programme entsprechen anpassen? Einfacher gesagt als getan. Kahan verweist auf eine Studie von Westley Weimer, der (hier mit George Necula) Millionen von Zeilen aus (Java)-Programmen untersucht hat und allein in der Art und Weise, wie die betreffenden Programme mit Laufzeitfehlern umgingen, hunderte von Programmierfehlern fand. Typischerweise waren dies Fehlerbehandlungs-Schritte, die nicht richtig "hinter sich aufräumten" und lose Enden zurückließen.

Für Kahan zeigt das einen fundamentalen Fehler in den (meisten) heute verwendeten Programmiersprachen auf. Seiner Meinung nach sollten Programmiersprachen den Programmierer zwingen, Prozeduren für den Umgang mit unerwarteten Situationen, also letztlich mit Abstürzen, vorzusehen. Stürzt ein Teil eines Programms ab, sollte es die Kontrolle an denjenigen Teil des Programms übergehen, der es aufgerufen hat - inklusive Informationen darüber, was schiefgegangen ist. Und derjenige Programmteil, der diese Meldung empfängt, sollte etwas mit dieser Meldung anzufangen wissen.

Programmiersprachen, die mit einem Compiler funktionieren - mit Software, welche die Programmbefehle vor Ausführung in solche Befehle übersetzt, die näher an der Maschinensprache des Computers liegen, und die bei der Übersetzung auch bestimmte Programmierfehler entdecken kann - sollten dieses Programmverhalten erzwingen, so Kahan: Der Programmierer sollte jeweils angeben müssen, was passiert, wenn ein Programmteil plötzlich durch den Absturz eines anderen Programmteils die Kontrolle übergeben bekommt. Andernfalls würde der Compiler das Programm gar nicht erst übersetzen.

Falls den Programmierern eine andere, bessere Möglichkeit einfällt, wie man sich auf das Unerwartete vorbereiten kann, dann lässt Kahan gerne mit sich reden. Aber irgendeine Voreinstellung, irgendein default sollte es für solche Fälle geben, damit sichergestellt ist, dass das Programm sich selbst dann vorhersehbar verhält, wenn der Programmierer oder die Programmiererin sich mit den Eventualitäten von Fehlverhalten gar nicht beschäftig haben.

So eine grundlegende Änderung durchzusetzen ist alles andere als einfach. Rückwirkend bekommt man die Änderung sowieso nicht hin (selbst die Umprogrammierungen für das deutlich einfachere Jahr-2000-Problem haben [die Schätzungen gehen auseinander] etwa 500 Milliarden Dollar gekostet).

Allenfalls kann man hoffen, dass zukünftige Versionen bestehender Programmiersprachen (oder natürlich ganz neue Sprachen) einen sichereren Umgang mit dem Kontrollwechsel implementieren. Freilich wird man dort auf das Problem stoßen, dass hinter den Programmiersprachen typischerweise unterschiedliche Motivationen sowie Vorstellungen davon stehen, wie eine elegante Programmiersprache aussehen sollte. Ob man die Programmierer in Punkto Kontrollübergabe bevormundet oder nicht, dazu werden unterschiedliche Sprachentwickler unterschiedliche Auffassungen haben.

Immerhin hat Vint Cerf, diesmal nicht in seinen Eigenschaften als Internetpionier oder Google-Vizepräsident, sondern als Präsident der Association for Computing Machinery, nach Kahans Vortrag beim HLF am Donnerstag gesagt, er wolle der Sache nachgehen. Wir werden sehen. Bislang ist Kahan eher so etwas wie der sprichwörtliche Rufer in der Wüste.

PS: Wer's noch nicht gesehen hat: Benjamin hatte hier bereits über Kahans Vortrag gebloggt.


4 Responses to “Ende ohne Schrecken: William Kahan und der geordnete Rückzug von Computerprogrammen”

  1. Martin Holzherr Reply | Permalink

    Die Lösung für unerwartete Laufzeitfehler gibt es in allen neuen Programmiersprachen bereits: Das Werfen von Ausnahmen und ihr Auffangen an Stellen, wo mit der geworfenen Ausnahme und der mit ihr assozierten Information etwas sinnvolles gemacht werden kann.
    Das tiefere Problem ist ein ganz anderes und lässt sich mit neuen formalen Programmiersprachelementen nicht abdecken: Die Semantik eines Programms kennt zuerst einmal - wenn überhaupt - der Programmierer, nicht aber der Compiler und auch nicht der Computer, der das Programm ausführt.

    Das beste Mittel um das Problem des Codedschungels zu lösen, der sich heute weniger in schlecht geschriebenen Codeteilen als vielmehr in übergrossen Programmquellcodes ausdrückt, ist es wohl, möglichst kurze Quellcodes anzustreben. Dazu müssten wohl ganz neue Programmierparadigmas entwickelt werden. Für die Steuerung von Flugzeugen und anderem komplexem Gerät könnte ich mir zum Beispiel vorstellen, dass das Flugzeug oder komplexe Gerät als physikalisches Modell in Software vorliegt wobei dazu eine allgemeine, gut getestete Bibkliothek, verwendet wird. Das Steuerungsprogramm selbst wäre dann relativ klein, weil es alle Probleme anhand des physikalischen Modells lösen würde.

  2. Gerald Reply | Permalink

    Definitiv kein leicht zu lösendes Problem. Denn was hier gefordert wird betrifft ja meist Situationen, die eben nicht im Vorfeld bedacht wurden. Ich weiß, genau da soll sich was ändern, aber wie mein Vorredner schon sagte, hinter die Fassade blickt allenfalls der Programmierer aber bislang sicher nicht der Compiler.
    Zudem arbeiten ja meist mehrere Menschen an einem Projekt und selbst wenn jeder für sich alleine ein perfektes Error-Handling baut, die Probleme treten ja meist im Zusammenspiel der einzelnen Komponenten auf.
    Dies ebenfalls zu überwachen übersteigt vom Grad der Komplexität glaube ich das Machbare.

  3. Dr. Webbaer Reply | Permalink

    Für Kahan zeigt das einen fundamentalen Fehler in den (meisten) heute verwendeten Programmiersprachen auf. Seiner Meinung nach sollten Programmiersprachen den Programmierer zwingen, Prozeduren für den Umgang mit unerwarteten Situationen, also letztlich mit Abstürzen, vorzusehen.

    Dies ist leider nicht möglich, denn die gemeinten "Programme", wie Software allgemein, unterstützen IMMER geschäftsmäßige oder sozusagen geschäftsmäßiges Verhalten der Primaten.

    Wenn also Software immer (zumindest: zum Teil) ohnehin vorhandene Logik unterstützt, kann es wegen der Fehlbarkeit des Primaten immer zu inkonsistenten Zuständen im "Programm" kommen.

    Dieser Zustand könnte dann vom Programm artikuliert werden ohne dass es "abstürzt", aber die Folgen wären dieselben oder ganz ähnlich.

    Der Primat ist also schuld, egal wie gut das Programm im Artikelsinne determiniert ist.

    MFG
    Dr. W (der denn auch ganz andere Programmierphilosophien kennt und schätzt)

  4. Dr. Webbaer Reply | Permalink

    Zudem arbeiten ja meist mehrere Menschen an einem Projekt und selbst wenn jeder für sich alleine ein perfektes Error-Handling baut, die Probleme treten ja meist im Zusammenspiel der einzelnen Komponenten auf.

    Wenn ein zur Laufzeit auftretender sozusagen primitiver Fehler ("Division durch Null", "Objekt nicht geladen" etc.) auftritt, wird idR eine brauchbare Fehlermeldung generiert - und manchmal auch das Programm abrupt geschlossen ("Absturz"). Das ist die eine Seite der Malaise, es ist schwierig dem Programm mitzugeben, was es in solchen Fällen tun soll. D.h. es ist nicht so schwierig, aber wenn eine derartige Fehlerbehandlung eingebaut ist, antizipiert ist, kann sie besser gleich programmtechnisch ausgeschlossen werden, statt in eine Fehlerbehandlung zu laufen.

    Dazu kommen natürlich noch die nicht seltenen Fehler, dass das Programm zwar genau tut, was es soll, dass dieses Sollen aber nicht der Anforderungslage ("Pflichtenheft") entspricht bzw, die Anforderungslage selbst fehlerhaft ist.

Leave a Reply


+ 5 = ten