Folklore von Programmierern und Ingenieuren (Teil 1)





Dies ist eine Sammlung von Geschichten aus dem Internet darüber, wie Fehler manchmal unglaubliche Manifestationen haben. Vielleicht haben Sie auch eine Geschichte zu erzählen.



Autoallergie gegen Vanilleeis



Eine Geschichte für Ingenieure, die verstehen, dass das Offensichtliche nicht immer die Lösung ist und dass die Fakten, egal wie unplausibel sie sind, Fakten sind. Die Pontiac Division der General Motors Corporation erhielt eine Beschwerde:



, , , . : . , , , , . Pontiac, . , , , . , . , , : « Pontiac, - , , , ?».


Wie Sie sich vorstellen können, war der Divisionspräsident skeptisch gegenüber dem Brief. Senden Sie jedoch für alle Fälle einen Techniker zur Überprüfung. Er war überrascht, von einem reichen, gut ausgebildeten Mann getroffen zu werden, der in einer wunderschönen Gegend lebte. Sie vereinbarten, sich gleich nach dem Abendessen zu treffen, um gemeinsam in die Eisdiele zu gehen. Es war Vanille in dieser Nacht, und als sie wieder ins Auto stiegen, fing es nicht an.



Der Ingenieur kam noch drei Abende. Das erste Mal war das Eis Schokolade. Das Auto sprang an. Das zweite Mal gab es Erdbeereis. Das Auto sprang an. Am dritten Abend bat er um Vanille. Das Auto sprang nicht an.



Nachdem der Ingenieur mit Bedacht argumentiert hatte, weigerte er sich, an die Allergie des Autos gegen Vanilleeis zu glauben. Daher habe ich mit dem Besitzer des Autos vereinbart, dass er seine Besuche fortsetzen wird, bis er eine Lösung für das Problem findet. Unterwegs machte er sich Notizen: Er schrieb alle Informationen, die Tageszeit, die Art des Benzins, die Ankunfts- und Rückkehrzeit aus dem Geschäft usw. auf.



Bald stellte der Ingenieur fest, dass der Besitzer des Autos weniger Zeit damit verbrachte, Vanilleeis zu kaufen. Der Grund war das Layout des Produkts im Geschäft. Vanilleeis war das beliebteste und wurde in einem separaten Gefrierschrank an der Vorderseite des Ladens aufbewahrt, um das Auffinden zu erleichtern. Und alle anderen Sorten befanden sich im hinteren Teil des Ladens, und es dauerte viel länger, die richtige Sorte zu finden und zu bezahlen.



Nun war die Frage für den Ingenieur: Warum startete das Auto nicht, wenn ab dem Moment, in dem der Motor abgestellt wurde, weniger Zeit verging? Da das Problem die Zeit war, nicht Vanilleeis, fand der Ingenieur schnell die Antwort: Es war eine Gasschleuse. Es trat jeden Abend auf, aber als der Besitzer des Autos mehr Zeit damit verbrachte, nach Eis zu suchen, hatte der Motor Zeit, sich ausreichend abzukühlen, und startete leise. Und als der Mann Vanilleeis kaufte, war der Motor immer noch zu heiß und die Gasschraube hatte keine Zeit, sich aufzulösen.



Moral: Selbst völlig verrückte Probleme können manchmal real sein.



Crash Bandicoot



Es ist schmerzhaft, das zu erleben. Als Programmierer gewöhnen Sie sich daran, Ihren Code zuerst, zweitens, drittens zu beschuldigen ... und irgendwo an der zehntausendsten Stelle geben Sie dem Compiler die Schuld. Und noch weiter unten in der Liste geben Sie der Ausrüstung bereits die Schuld.



Hier ist meine Geschichte über einen Hardwarefehler.



Für das Crash Bandicoot-Spiel habe ich einen Code zum Laden und Speichern auf einer Speicherkarte geschrieben. Für einen so selbstgerechten Spieleentwickler war es wie ein Spaziergang in einem Park: Ich dachte, die Arbeit würde mehrere Tage dauern. Infolgedessen habe ich den Code jedoch sechs Wochen lang getestet. Ich habe andere Probleme auf dem Weg gelöst, aber alle paar Tage bin ich für einige Stunden zu diesem Code zurückgekehrt. Es war eine Qual.



Das Symptom sah folgendermaßen aus: Wenn Sie das aktuelle Durchspielen des Spiels speichern und auf die Speicherkarte zugreifen, läuft fast immer alles gut ... Aber manchmal wird der Lese- oder Schreibvorgang ohne ersichtlichen Grund durch eine Zeitüberschreitung abgeschlossen. Kurze Aufnahmen beschädigen häufig die Speicherkarte. Wenn ein Spieler versucht zu speichern, kann er nicht nur nicht speichern, sondern zerstört auch die Karte. Pfannkuchen.



Nach einer Weile geriet unser Produzent bei Sony, Connie Bus, in Panik. Wir konnten das Spiel mit diesem Fehler nicht ausliefern, und nach sechs Wochen verstand ich nicht, was die Ursache für dieses Problem war. Über Connie haben wir andere PS1-Entwickler kontaktiert: Ist jemand auf ein ähnliches Problem gestoßen? Nein. Niemand hatte Probleme mit der Speicherkarte.



Wenn Sie keine Ideen zum Debuggen haben, ist fast der einzige Ansatz "Teilen und Erobern": Sie entfernen immer mehr Code aus dem fehlerhaften Programm, bis ein relativ kleines Fragment vorhanden ist, das immer noch ein Problem verursacht. Das heißt, Sie schneiden das Programm Stück für Stück ab, bis der Teil, der den Fehler enthält, erhalten bleibt.



Aber der Punkt ist, es ist sehr schwierig, Teile aus einem Videospiel herauszuschneiden. Wie wird es ausgeführt, wenn Sie den Schwerkraftemulationscode entfernt haben? Oder Zeichen zeichnen?



Daher müssen Sie ganze Module durch Stubs ersetzen, die vorgeben, etwas Nützliches zu tun, aber tatsächlich etwas sehr Einfaches tun, das keine Fehler enthalten kann. Wir müssen solche Krücken schreiben, damit das Spiel funktioniert. Es ist ein langsamer und schmerzhafter Prozess.



Kurz gesagt, ich habe es geschafft. Ich habe immer mehr Code entfernt, bis es einen ersten Code gab, der das System zum Starten des Spiels einrichtet, die Ausrüstung für das Rendern initialisiert usw. Zu diesem Zeitpunkt konnte ich das Menü zum Speichern und Laden natürlich nicht erstellen, da ich für den gesamten Grafikcode einen Stub erstellen musste. Aber ich könnte so tun, als wäre ich ein Benutzer, der den (unsichtbaren) Bildschirm zum Speichern und Laden verwendet und zum Speichern und anschließenden Schreiben auf die Speicherkarte auffordert.



Infolgedessen blieb mir ein kleiner Code übrig, der immer noch das oben genannte Problem hatte - aber bisher geschah dies zufällig! Die meiste Zeit funktionierte alles gut, aber gelegentlich gab es Abstürze. Ich habe fast den gesamten Spielcode entfernt, aber der Fehler lebte weiter. Das war rätselhaft: Der verbleibende Code hat eigentlich nichts getan.



Irgendwann, wahrscheinlich um drei Uhr morgens, kam mir ein Gedanke. Lese- und Schreibvorgänge (E / A) setzen ein genaues Timing voraus. Bei der Arbeit mit einer Festplatte, einer Speicherkarte oder einem Bluetooth-Modul entspricht der für das Lesen und Schreiben verantwortliche Low-Level-Code den Taktimpulsen.



Mit Hilfe einer Uhr wird ein Gerät, das nicht direkt mit dem Prozessor verbunden ist, mit dem im Prozessor ausgeführten Code synchronisiert. Die Uhr bestimmt die Baudrate - die Baudrate. Wenn es eine Verwechslung mit den Timings gibt, sind entweder die Hardware oder die Software oder beide ebenfalls verwechselt. Und das ist sehr schlecht, weil die Daten beschädigt werden können.



Was ist, wenn etwas in unserem Code das Timing verwirrt? Ich habe alles im Code des Testprogramms überprüft und festgestellt, dass wir den programmierbaren Timer in der PS1 auf eine Frequenz von 1 kHz (1000 Zyklen pro Sekunde) eingestellt haben. Dies ist standardmäßig ziemlich viel. Wenn die Set-Top-Box gestartet wird, läuft sie mit 100 Hz. Und die meisten Spiele verwenden diese Frequenz.



Andy, der Entwickler des Spiels, stellte den Timer auf 1 kHz ein, damit die Bewegungen genauer berechnet wurden. Andy ist anfällig für Übermaß, und wenn wir die Schwerkraft emulieren, dann tun wir es so genau wie möglich!



Was aber, wenn das Beschleunigen des Timers das Gesamt-Timing des Programms und damit die Uhr, die die Baudrate für die Speicherkarte anpasst, irgendwie beeinflusst?



Ich habe den Timer-Code auskommentiert. Der Fehler ist nie wieder aufgetreten. Dies bedeutet jedoch nicht, dass wir das Problem behoben haben, da der Fehler zufällig aufgetreten ist. Was ist, wenn ich gerade Glück habe?



Einige Tage später experimentierte ich erneut mit dem Testprogramm. Der Fehler wurde nicht wiederholt. Ich kehrte zur vollständigen Codebasis des Spiels zurück und änderte den Speicher- und Ladecode so, dass der programmierbare Timer vor dem Zugriff auf die Speicherkarte auf seinen ursprünglichen Wert (100 Hz) zurückgesetzt und dann wieder auf 1 kHz zurückgesetzt wurde. Es gab keine Abstürze mehr.



Aber warum ist das passiert?



Ich ging wieder zum Testprogramm zurück. Ich habe versucht, mit einem 1-kHz-Timer eine gewisse Regelmäßigkeit beim Auftreten eines Fehlers zu finden. Schließlich bemerkte ich, dass der Fehler auftritt, wenn jemand mit dem PS1-Controller spielt. Da ich dies selten selbst tun würde - warum sollte ich beim Testen des Speicher- und Ladecodes einen Controller benötigen? - dann habe ich diese Abhängigkeit nicht bemerkt. Aber eines Tages wartete einer unserer Künstler darauf, dass ich mit dem Testen fertig war - ich fluchte wahrscheinlich in diesem Moment - und drehte nervös den Controller in seinen Händen. Ein Fehler ist aufgetreten. "Warte was ?! Nun, mach es noch einmal! "



Als ich feststellte, dass diese beiden Ereignisse miteinander verbunden sind, konnte ich den Fehler leicht reproduzieren: Ich begann auf die Speicherkarte zu schreiben, bewegte den Controller und beschädigte die Speicherkarte. Für mich sah es nach einem Hardwarefehler aus.



Ich ging zu Connie und erzählte von meiner Entdeckung. Sie gab die Informationen an einen der Ingenieure weiter, die die PS1 entworfen hatten. "Unmöglich", antwortete er, "es kann kein Hardwareproblem sein." Ich bat Connie, mit uns zu sprechen.



Der Ingenieur rief mich an und wir stritten uns mit ihm in seinem gebrochenen Englisch und meinem (extrem) gebrochenen Japanisch. Schließlich sagte ich: "Lassen Sie mich einfach mein 30-Zeilen-Testprogramm einschicken, bei dem die Bewegung des Controllers einen Fehler verursacht." Er hat zugestimmt. Sagte, es sei Zeitverschwendung und er sei furchtbar damit beschäftigt, an einem neuen Projekt zu arbeiten, aber er würde aufgeben, weil wir ein sehr wichtiger Entwickler für Sony sind. Ich räumte mein Testprogramm auf und schickte es ihm.



Am nächsten Abend (wir waren in Los Angeles und er war in Tokio) rief er mich an und entschuldigte sich verlegen. Es war ein Hardwareproblem.



Ich weiß nicht genau, was der Fehler war, aber nach dem, was ich in der Sony-Zentrale gehört habe, würde das Einstellen des Timers auf einen ausreichend hohen Wert die Komponenten auf dem Motherboard in der Nähe des Timer-Kristalls beeinträchtigen. Einer davon war der Baudraten-Controller der Speicherkarte, der auch die Baudrate für die Controller einstellte. Ich bin kein Ingenieur, also hätte ich vielleicht etwas verwirrt.



Unter dem Strich gab es jedoch Interferenzen zwischen den Komponenten auf dem Motherboard. Und wenn gleichzeitig Daten über den Controller-Port und den Speicherkarten-Port mit einem Timer übertragen wurden, der mit einer Frequenz von 1 kHz arbeitet, gingen die Bits verloren, Daten gingen verloren und die Karte wurde beschädigt.



Schlechte Kühe



In den 1980er Jahren schrieb mein Mentor Sergei Software für den CM-1800, einen sowjetischen Klon des PDP-11. Dieser Mikrocomputer wurde gerade an einem Bahnhof in der Nähe von Swerdlowsk installiert, einem wichtigen Verkehrsknotenpunkt in der UdSSR. Das neue System wurde für die Weiterleitung von Waggons und Güterströmen entwickelt. Es stellte sich jedoch heraus, dass es sich um einen nervigen Fehler handelte, der zu zufälligen Abstürzen und Abstürzen führte. Stürze traten immer dann auf, wenn jemand abends nach Hause ging. Trotz sorgfältiger Untersuchungen am nächsten Tag funktionierte der Computer bei allen manuellen und automatisierten Tests ordnungsgemäß. Dies weist normalerweise auf eine Race-Bedingung oder einen anderen Parallelitätsfehler hin, der sich unter bestimmten Bedingungen manifestiert. Sergei war es leid, bis spät in die Nacht zu telefonieren, und beschloss, der Sache auf den Grund zu gehen und zunächst zu verstehen, welche Bedingungen auf dem Rangierbahnhof zu einem Ausfall des Computers führten.



Zunächst sammelte er Statistiken über alle ungeklärten Stürze und erstellte eine Grafik basierend auf Datum und Uhrzeit. Das Muster war offensichtlich. Nach einigen weiteren Tagen erkannte Sergey, dass er den Zeitpunkt zukünftiger Systemausfälle leicht vorhersagen konnte.



Er erfuhr bald, dass Störungen nur auftraten, wenn die Station Viehwagen aus der Nordukraine und Westrussland zu einem nahe gelegenen Schlachthof sortierte. Das an sich war seltsam, weil der Schlachthof von Farmen versorgt wurde, die in Kasachstan viel näher lagen.



Das Kernkraftwerk Tschernobyl explodierte 1986 und radioaktive Niederschläge machten die Umgebung unbewohnbar. Große Gebiete in der Nordukraine, in Weißrussland und in Westrussland sind kontaminiert. Sergei vermutete eine hohe Strahlung in ankommenden Autos und entwickelte eine Methode, um diese Theorie zu testen. Der Bevölkerung war es verboten, Dosimeter zu haben, deshalb setzte Sergei mehrere Militärs am Bahnhof ab. Nach mehreren Wodka-Getränken gelang es ihm, den Soldaten davon zu überzeugen, den Strahlungspegel in einem der verdächtigen Autos zu messen. Es stellte sich heraus, dass der Pegel um ein Vielfaches höher ist als die üblichen Werte.



Das Vieh strahlte nicht nur starke Strahlung aus, sein Pegel war auch so hoch, dass es zu einem versehentlichen Verlust von Bits im Gedächtnis des CM-1800 führte, der sich im Gebäude neben der Station befand.



In der UdSSR herrschte Nahrungsmittelknappheit, und die Behörden beschlossen, "Tschernobyl" -Fleisch mit Fleisch aus anderen Regionen des Landes zu mischen. Dies ermöglichte es, das Gesamtniveau der Radioaktivität zu reduzieren, ohne wertvolle Ressourcen zu verlieren. Als Sergei davon erfuhr, füllte er sofort die Auswanderungsdokumente aus. Und die Stürze des Computers hörten von selbst auf, als die Strahlung mit der Zeit abnahm.



Durch die Rohre



Movietech Solutions hat einmal eine Software für Kinos für das Ticketing, das Ticketing und die allgemeine Verwaltung entwickelt. Die DOS-Version der Flaggschiff-Anwendung war bei kleinen und mittleren Theaterketten in Nordamerika sehr beliebt. Kein Wunder also, dass die Windows 95-Version, die in die neuesten Touchscreens und Self-Service-Kioske integriert und mit allen Arten von Berichterstellungstools ausgestattet wurde, schnell populär wurde. Die meiste Zeit verlief das Update reibungslos. IT-Experten vor Ort installierten neue Hardware, migrierten Daten und das Geschäft wurde fortgesetzt. Außer wenn es nicht weiterging. Als dies geschah, schickte die Firma James the Cleaner.



Obwohl dieser Spitzname auf den schändlichen Typ anspielt, ist der Reiniger nur eine Kombination aus Ausbilder, Installateur und Alleskönner. James konnte einige Tage beim Kunden verbringen, um alle Komponenten zusammenzusetzen, und dann brachte er den Mitarbeitern einige Tage bei, wie man das neue System verwendet, etwaige Hardwareprobleme behebt und die Software tatsächlich dabei unterstützt, ihre Entwicklungsphase zu durchlaufen.



Daher ist es nicht verwunderlich, dass James zu dieser hektischen Zeit am Morgen ins Büro kam und keine Zeit hatte, seinen Schreibtisch zu erreichen, als er vom Chef begrüßt wurde, der überdurchschnittlich mit Koffein gefüllt war.



„Ich fürchte, Sie müssen so schnell wie möglich nach Annapolis in Nova Scotia reisen. Ihr gesamtes System ist ausgefallen, und nach einer Nacht der Zusammenarbeit mit ihren Ingenieuren können wir nicht herausfinden, was passiert ist. Es sieht so aus, als ob der Server einen Netzwerkfehler hat. Aber erst nachdem das System einige Minuten funktioniert hat.



- Sie sind nicht zum alten System zurückgekehrt? - James antwortete ziemlich ernst, obwohl sich seine Augen vor Überraschung weiteten.



- Genau: Ihr IT-Spezialist "hat die Prioritäten geändert" und er hat beschlossen, mit ihrem alten Server zu gehen. James, sie haben das System an sechs Standorten installiert und gerade für Premium-Support bezahlt, und ihr Geschäft läuft jetzt in den 1950er Jahren.



James richtete sich leicht auf.



- Das ist eine andere Sache. Okay, lass uns anfangen.



Als er in Annapolis ankam, fand er als erstes das erste Kino des Kunden, das ein Problem hatte. Auf der am Flughafen aufgenommenen Karte sah alles anständig aus, aber die Umgebung der gewünschten Adresse sah verdächtig aus. Kein Ghetto, aber erinnert an Film Noir. Als James am Bordstein in der Mitte parkte, kam eine Prostituierte auf ihn zu. Angesichts der Größe von Annapolis war es höchstwahrscheinlich das einzige in der ganzen Stadt. Ihr Auftritt erinnerte sofort an die berühmte Figur, die Sex für Geld auf der großen Leinwand anbot. Nein, nicht über Julia Roberts, sondern über Jon Voight [ein Hinweis auf den Film "Midnight Cowboy" - ca. pro. ].



Nachdem er die Prostituierte nach Hause geschickt hatte, ging James ins Kino. Die Umgebung ist besser geworden, aber dennoch entsteht der Eindruck von Schäbigkeit. Nicht dass James zu besorgt gewesen wäre. Er war schon an schmutzigen Orten gewesen. Und dies war Kanada, wo sogar die Räuber höflich genug sind, sich zu bedanken, nachdem sie Ihre Brieftasche genommen haben.



Der Seiteneingang zum Kino befand sich in einer feuchten Gasse. James ging zur Tür und klopfte an. Bald knarrte sie und öffnete sich ein wenig.



- Bist du ein Putzer? Eine heisere Stimme kam von innen.



„Ja, ich bin es… ich bin gekommen, um alles zu reparieren.



James ging in die Lobby des Kinos. Wahrscheinlich ohne andere Wahl begannen die Mitarbeiter, den Besuchern Papiertickets auszustellen. Dies machte die Finanzberichterstattung schwierig, geschweige denn interessantere Details. Aber das Personal begrüßte James mit Erleichterung und brachte ihn sofort in den Serverraum.



Auf den ersten Blick war alles in Ordnung. James loggte sich in den Server ein und überprüfte die üblichen verdächtigen Stellen. Keine Probleme. Als Vorsichtsmaßnahme fuhr James jedoch den Server herunter, ersetzte die Netzwerkkarte und rollte das System zurück. Sie fing sofort an, voll zu arbeiten. Das Personal begann wieder Tickets zu verkaufen.



James rief Mark an und berichtete über die Situation. Es ist nicht schwer anzunehmen, dass James hier verweilen und sehen möchte, ob etwas Unerwartetes passiert. Er ging die Treppe hinunter und begann das Personal zu befragen, was passiert war. Offensichtlich funktioniert das System nicht mehr. Sie schalteten es aus und wieder ein, es funktionierte. Aber nach 10 Minuten fiel das System aus.



In diesem Moment passierte etwas Ähnliches. Plötzlich gab das Ticketingsystem Fehler aus. Das Personal seufzte und schnappte sich die Papiertickets, und James eilte zum Serverraum. Mit dem Server sah alles gut aus.



Dann trat einer der Mitarbeiter ein.



- Das System funktioniert wieder.



James war verwirrt, weil er nichts getan hatte. Genauer gesagt, nichts, was das System zum Laufen bringen würde. Er loggte sich aus, nahm den Hörer ab und rief das Support-Team seines Unternehmens an. Bald betrat derselbe Mitarbeiter den Serverraum.



- Das System lügt.



James warf einen Blick auf den Server. Ein interessantes und bekanntes Muster aus bunten Formen tanzte auf dem Bildschirm - chaotisch verdrehte und ineinander verschlungene Rohre. Wir haben alle diesen Bildschirmschoner einmal gesehen. Es wurde wunderschön gerendert und buchstäblich hypnotisiert.





James drückte den Knopf und das Muster verschwand. Er eilte zur Kasse und traf unterwegs den Angestellten, der zu ihm zurückkehrte.



- Das System funktioniert wieder.



Wenn du mental eine Gesichtspalme machen kannst, dann hat James genau das getan. Bildschirmschoner. Es verwendet OpenGL. Während des Betriebs werden daher alle Ressourcen des Serverprozessors verbraucht. Infolgedessen läuft jede Anforderung an den Server ab.



James ging zurück in den Serverraum, loggte sich ein und ersetzte den schönen Pipes-Bildschirmschoner durch einen leeren Bildschirm. Das heißt, anstelle eines Bildschirmschoners, der 100% der Prozessorressourcen verbraucht, habe ich einen anderen installiert, der keine Ressourcen verbraucht. Dann wartete ich 10 Minuten, um meine Vermutung zu überprüfen.



Als James im nächsten Kino ankam, fragte er sich, wie er seinem Vorgesetzten erklären sollte, dass er gerade 800 km geflogen war, um den Bildschirmschoner auszuschalten.



Absturz in einer bestimmten Mondphase



Eine glaubwürdige Geschichte. Es gab einmal einen Softwarefehler, der von der Mondphase abhing. Es gab eine kleine Unterroutine, die üblicherweise in verschiedenen MIT-Programmen verwendet wurde, um die Annäherung an die wahre Mondphase zu berechnen. GLS hat diese Unterroutine in ein LISP-Programm integriert, das beim Schreiben einer Datei eine Zeitstempelzeichenfolge mit einer Länge von fast 80 Zeichen ausgibt. Es war sehr selten, dass die erste Zeile einer Nachricht zu lang war und zur nächsten Zeile überging. Und als das Programm diese Datei dann las, fluchte es. Die Länge der ersten Zeile hing vom genauen Datum und der Uhrzeit sowie von der Länge der Phasenspezifikation zum Zeitpunkt des Drucks des Zeitstempels ab. Das heißt, der Fehler hing buchstäblich von der Mondphase ab!



Erste Papierausgabe der Jargon-Datei(Steele-1983) enthielt ein Beispiel einer solchen Zeichenfolge, die zu dem beschriebenen Fehler führte, aber der Compositor "reparierte" ihn. Es wurde seitdem als "Mondphasenfehler" beschrieben.



Seien Sie jedoch vorsichtig mit Annahmen. Vor einigen Jahren stießen Ingenieure am CERN (Europäisches Zentrum für Kernforschung) auf Fehler bei Experimenten, die am Large Electron-Positron Collider durchgeführt wurden. Da Computer die enorme Datenmenge, die von diesem Gerät generiert wird, aktiv verarbeiten, bevor sie das Ergebnis den Wissenschaftlern zeigen, haben viele angenommen, dass die Software irgendwie empfindlich auf die Mondphase reagiert. Mehrere verzweifelte Ingenieure gingen der Wahrheit auf den Grund. Der Fehler trat aufgrund einer geringfügigen Änderung der Geometrie des 27 km langen Rings aufgrund der Verformung der Erde während des Durchgangs des Mondes auf! Diese Geschichte trat in die Folklore der Physiker als "Newtons Rache an der Teilchenphysik" und als Beispiel für die Verbindung zwischen den einfachsten und ältesten physikalischen Gesetzen mit den fortschrittlichsten wissenschaftlichen Konzepten ein.



Das Spülen der Toilette hält den Zug an



Der beste Hardware-Fehler, von dem ich gehört habe, war in einem Hochgeschwindigkeitszug in Frankreich. Der Fehler führte zu einer Notbremsung des Zuges, jedoch nur, wenn Passagiere an Bord waren. In jedem Fall wurde der Zug außer Betrieb genommen, überprüft, aber nichts gefunden. Dann wurde er zurück in die Leitung geschickt und sofort gestoppt.



Während einer der Kontrollen ging ein im Zug reisender Ingenieur zur Toilette. Bald wusch es sich von selbst weg, BOOM! Not-Halt.



Der Ingenieur kontaktierte den Fahrer und fragte:



- Was haben Sie kurz vor dem Bremsen gemacht?



- Nun, ich habe den Abstieg verlangsamt ...



Es war seltsam, weil der Zug während des normalen Fahrens Dutzende Male auf den Pisten langsamer wird. Der Zug fuhr weiter und beim nächsten Abstieg warnte der Fahrer:



- Ich werde langsamer.



Nichts ist passiert.



- Was hast du mit dem letzten Bremsen gemacht? - fragte der Fahrer.



- Nun ... ich war auf der Toilette ...



- Nun, dann geh auf die Toilette und mach was du getan hast, als wir wieder runter gingen!



Der Ingenieur ging zur Toilette und als der Fahrer warnte: "Ich bremse", spülte er das Wasser. Natürlich hielt der Zug sofort an.



Jetzt konnten sie das Problem reproduzieren und mussten die Ursache finden.



Nach zwei Minuten bemerkten sie, dass das Fernbedienungskabel für die Motorbremsung (der Zug hatte an beiden Enden einen Motor) von der Wand des Schaltschranks getrennt war und auf dem Relais lag, das den Magnet für den Toilettenstecker steuerte ... Als das Relais eingeschaltet wurde, störte es das Bremskabel und das System Der Crash-Schutz beinhaltete lediglich eine Notbremsung.



Das Tor, das FORTRAN hasste



Vor einigen Monaten stellten wir fest, dass die Netzwerkverbindungen auf dem Festland [dies war in Hawaii] sehr, sehr langsam wurden. Es könnte 10-15 Minuten dauern und dann plötzlich wieder auftauchen. Nach einer Weile beschwerte sich ein Kollege bei mir, dass die Netzwerkverbindungen auf dem Festland überhaupt nicht funktionierten. Er hatte FORTRAN-Code, der auf einen Computer auf dem Festland kopiert werden musste, aber er funktionierte nicht, weil "das Netzwerk nicht lange genug dauerte, bis der FTP-Upload abgeschlossen war".



Ja, es stellte sich heraus, dass Netzwerkfehler auftraten, als ein Kollege versuchte, die FORTRAN-Quelldatei auf einen Computer auf dem Festland zu übertragen. Wir haben versucht, die Datei zu archivieren: Dann wurde sie leise kopiert (aber auf dem Zielcomputer befand sich kein Entpacker, sodass das Problem nicht gelöst wurde). Schließlich haben wir den FORTRAN-Code in sehr kleine Teile "aufgeteilt" und einzeln versendet. Die meisten Fragmente wurden ohne Probleme kopiert, aber einige funktionierten nicht oder nach zahlreichen Versuchen.



Nachdem wir die Problemfragmente untersucht hatten, stellten wir fest, dass sie etwas gemeinsam haben: Sie enthalten alle Kommentarblöcke, die mit Zeilen beginnen und enden, die aus C-Großbuchstaben bestehen (ein Kollege hat es vorgezogen, FORTRAN zu kommentieren). Wir haben E-Mails an das Netzwerk an die Netzwerkspezialisten gesendet und um Hilfe gebeten. Natürlich wollten sie Beispiele unserer Dateien sehen, die nicht per FTP gesendet werden konnten ... aber unsere Briefe erreichten sie nicht. Schließlich haben wir eine einfache Beschreibung erstellt, wie nicht weitergeleitete Dateien aussehen. Es hat funktioniert :) [Traue ich mich, hier ein Beispiel für einen der problematischen Kommentare zu FORTRAN hinzuzufügen? Wahrscheinlich nicht wert!]



Am Ende haben wir es geschafft, es herauszufinden. Kürzlich wurde ein neues Gateway zwischen unserem Teil des Campus und dem Festlandnetz installiert. Er hatte RIESIGE Schwierigkeiten, Pakete zu übertragen, die doppelte Cs in Großbuchstaben enthielten! Nur wenige dieser Pakete können alle Ressourcen des Gateways beanspruchen und verhindern, dass die meisten anderen Pakete durchbrechen. Wir haben uns beim Gateway-Hersteller beschwert ... und sie sagten uns: „Oh ja, Sie sind auf einen doppelten C-Fehler gestoßen! Wir wissen bereits über ihn. " Am Ende haben wir das Problem durch den Kauf eines neuen Gateways von einem anderen Hersteller gelöst (zur Verteidigung des ersteren werde ich sagen, dass die Unfähigkeit, Programme für jemanden an FORTRAN zu übertragen, von Vorteil sein kann!).



Harte Zeiten



Vor einigen Jahren musste ich bei der Arbeit an einem Perl-ETL-System, mit dem die Kosten für klinische Phase-3-Studien gesenkt werden sollen, etwa 40.000 Daten verarbeiten. Zwei von ihnen haben den Test nicht bestanden. Das hat mich nicht allzu sehr gestört, da diese Daten den vom Kunden zur Verfügung gestellten Daten entnommen wurden, was oft, sagen wir, überraschend war. Als ich die anfänglichen Daten überprüfte, stellte sich heraus, dass diese Daten der 1. Januar 2011 und der 1. Januar 2007 waren. Ich dachte, dass der Fehler in dem Programm war, das ich gerade geschrieben habe, aber es stellte sich heraus, dass es bereits 30 Jahre alt war. Dies mag für diejenigen, die mit dem Software-Ökosystem nicht vertraut sind, mysteriös klingen. Aufgrund der langjährigen Entscheidung eines anderen Unternehmens, Geld zu verdienen, bezahlte mich mein Kunde, um einen Fehler zu beheben, den ein Unternehmen versehentlich und ein anderes absichtlich eingeführt hatte. Damit Sie verstehen, worum es geht,Ich muss Ihnen von der Firma erzählen, die die Funktion hinzugefügt hat, die als Ergebnis zu einem Fehler wurde, sowie von einigen anderen merkwürdigen Ereignissen, die zu dem mysteriösen Fehler beigetragen haben, den ich behoben habe.



In guten alten Zeiten setzten Apple-Computer ihr Datum manchmal spontan auf den 1. Januar 1904 zurück. Der Grund war einfach: Eine batteriebetriebene "Systemuhr" wurde verwendet, um Datum und Uhrzeit zu verfolgen. Was ist passiert, als die Batterie leer war? Computer begannen, das Datum seit Beginn der Ära um die Anzahl der Sekunden zu verfolgen. Die Epoche bedeutete das ursprüngliche Referenzdatum, und für den Macintosh war es der 1. Januar 1904. Nachdem die Batterie leer war, wurde das aktuelle Datum auf das angegebene Datum zurückgesetzt. Aber warum ist das passiert?



Zuvor verwendete Apple 32 Bit, um die Anzahl der Sekunden ab dem ursprünglichen Datum zu speichern. Ein Bit kann einen von zwei Werten speichern - 1 oder 0. Zwei Bits können einen von vier Werten speichern: 00, 01, 10, 11. Drei Bits - ein Wert von acht: 000, 001, 010, 011, 100, 101, 110, 111 usw. Und 32 könnte einen von 2 32 Werten speichern , dh 4 294 967 296 Sekunden. Bei Apple-Daten war dies ungefähr 136 Jahre alt, sodass ältere Macs keine Daten nach 2040 verarbeiten können. Wenn die Systembatterie leer ist, wird das Datum ab Beginn der Epoche auf 0 Sekunden zurückgesetzt, und Sie müssen das Datum jedes Mal manuell einstellen, wenn Sie den Computer einschalten (oder bis Sie eine neue Batterie kaufen).



Die Entscheidung von Apple, Datumsangaben als Sekunden ab Beginn der Epoche zu speichern, bedeutete jedoch, dass wir Datumsangaben vor Beginn der Epoche nicht verarbeiten konnten, was, wie wir sehen werden, weitreichende Auswirkungen hatte. Apple hat eine Funktion eingeführt, keinen Fehler. Dies bedeutete unter anderem, dass das Macintosh-Betriebssystem immun gegen den "Millennium-Bug" war (was nicht über viele Mac-Anwendungen gesagt werden kann, die über eigene Datumssysteme zur Umgehung von Einschränkungen verfügten).



Mach weiter. Wir haben Lotus 1-2-3 verwendet, die von IBM entwickelte "Killer-Anwendung", die zum Start der PC-Revolution beigetragen hat, obwohl Apple-Computer über VisiCalc verfügten, das Personal Computer erfolgreich machte. Um fair zu sein, wenn 1-2-3 nicht erschienen wäre, wären PCs kaum gestartet, und die Geschichte der PCs hätte sich sehr unterschiedlich entwickeln können. Lotus 1-2-3 behandelte 1900 fälschlicherweise als Schaltjahr. Als Microsoft seine erste Multiplan-Tabelle veröffentlichte, hatte es einen kleinen Marktanteil. Als wir das Excel-Projekt starteten, beschlossen wir, nicht nur das Namensschema für Zeilen und Spalten aus Lotus 1-2-3 zu kopieren, sondern auch die Kompatibilität für Fehler sicherzustellen und 1900 bewusst als Schaltjahr zu behandeln. Dieses Problem besteht bis heute. Das heißt, in 1-2-3 war es ein Fehler, und in Excel war es eine bewusste Entscheidung, die garantiertdass alle 1-2-3 Benutzer ihre Tabellenkalkulationen in Excel importieren können, ohne die Daten zu ändern, auch wenn sie falsch sind.



Aber es gab noch ein anderes Problem. Microsoft veröffentlichte erstmals Excel für den Macintosh, das Daten erst am 1. Januar 1904 erkannte. In Excel galt der 1. Januar 1900 als Beginn einer Ära. Daher haben die Entwickler eine Änderung vorgenommen, damit ihr Programm den Typ der Epoche erkennt und die Daten entsprechend der gewünschten Epoche in sich selbst speichert. Microsoft hat sogar einen erklärenden Artikel darüber geschrieben. Und diese Entscheidung führte zu meinem Fehler.



Mein ETL-System erhielt Excel-Tabellen von Kunden, die unter Windows erstellt wurden, aber auch auf einem Mac erstellt werden konnten. Daher könnte der Beginn einer Ära in der Tabelle entweder der 1. Januar 1900 oder der 1. Januar 1904 sein. Wie finde ich es heraus? Das Excel-Dateiformat zeigt die erforderlichen Informationen an, aber der von mir verwendete Parser wurde nicht angezeigt (jetzt), und es wird davon ausgegangen, dass Sie die Ära für eine bestimmte Tabelle kennen. Wahrscheinlich könnte ich mehr Zeit damit verbringen, die Excel-Binärdatei zu verstehen und den Patch an den Autor des Parsers zu senden, aber ich hatte viel für den Client zu tun, also schrieb ich schnell eine Heuristik, um die Epoche zu bestimmen. Es war einfach.



In Excel kann das Datum 5. Juli 1998 im Format "07-05-98" (nutzloses amerikanisches System), "5. Juli 98", "5. Juli 1998", "5. Juli 98" oder in einigen dargestellt werden Ein anderes nutzloses Format (ironischerweise war eines der Formate, die meine Excel-Version nicht anbot, der ISO 8601-Standard). In der Tabelle wurde das unformatierte Datum jedoch entweder als "35981" für die Epoche 1900 oder als "34519" für die Epoche 1904 gespeichert (die Zahlen geben die Anzahl der Tage seit Beginn der Epoche an). Ich habe nur einen einfachen Parser verwendet, um das Jahr aus dem formatierten Datum zu extrahieren, und dann den Excel-Parser verwendet, um das Jahr aus dem unformatierten Datum zu extrahieren. Wenn sich beide Werte um 4 Jahre unterschieden, verstand ich, dass ich das System mit der Ära 1904 verwendete.



Warum habe ich nicht einfach formatierte Daten verwendet? Da der 5. Juli 1998 als "Juli 98" formatiert werden kann, fehlt der Tag des Monats. Wir haben Tabellen von so vielen Unternehmen erhalten, die sie auf so unterschiedliche Weise erstellt haben, dass wir (in diesem Fall ich) mit den Daten umgehen mussten. Und wenn Excel es richtig macht, sollten wir es auch tun!



Dann stieß ich auf 39082. Lassen Sie mich daran erinnern, dass Lotus 1-2-3 1900 als Schaltjahr betrachtete, und dies wurde in Excel getreu wiederholt. Und da dies einen Tag zu 1900 hinzufügte, könnten viele Datumsfunktionen für genau diesen Tag falsch sein. Das heißt, 39082 könnte der 1. Januar 2011 (auf Macs) oder der 31. Dezember 2006 (unter Windows) gewesen sein. Wenn mein "Jahre-Parser" 2011 aus dem formatierten Wert extrahiert hat, ist alles in Ordnung. Da der Excel-Parser jedoch nicht weiß, welche Epoche verwendet werden soll, wird standardmäßig die Epoche 1900 verwendet, die 2006 zurückgibt. Meine Anwendung stellte fest, dass es einen Unterschied von 5 Jahren gab, betrachtete dies als Fehler, protokollierte und gab einen unformatierten Wert zurück.



Um dies zu umgehen, habe ich Folgendes geschrieben (Pseudocode):



diff = formatted_year - parsed_year
if 0 == diff
    assume 1900 date system
if 4 == diff
    assume 1904 date system
if 5 == diff and month is December and day is 31
    assume 1904 date system


Und dann wurden alle 40.000 Daten korrekt analysiert.



Inmitten großer Druckaufträge



In den frühen 1980er Jahren arbeitete mein Vater bei Storage Technology, einem nicht mehr existierenden Geschäftsbereich, der Bandlaufwerke und pneumatische Systeme für die Hochgeschwindigkeits-Bandzufuhr baute.



Sie haben die Laufwerke so umgestaltet, dass ein zentrales Laufwerk "A" mit sieben Laufwerken "B" verbunden sein kann und das kleine Betriebssystem im RAM, das das Laufwerk "A" steuert, Lese- und Schreibvorgänge an alle Laufwerke "B" delegieren kann.



Jedes Mal, wenn Laufwerk "A" gestartet wurde, musste eine Diskette in das mit "A" verbundene Peripherie-Laufwerk eingelegt werden, um das Betriebssystem in seinen Speicher zu laden. Es war äußerst primitiv: Die Rechenleistung wurde von einem 8-Bit-Mikrocontroller bereitgestellt.



Die Zielgruppe für solche Geräte waren Unternehmen mit sehr großen Datenspeichern - Banken, Einzelhandelsketten usw. -, die viele Adressetiketten oder Kontoauszüge drucken mussten.



Ein Kunde hatte ein Problem. Während eines Druckauftrags kann ein bestimmtes Laufwerk "A" nicht mehr funktionieren, wodurch der gesamte Auftrag ausgeführt wird. Um das Laufwerk wieder zum Laufen zu bringen, mussten die Mitarbeiter alles neu starten. Und wenn dies mitten in einer sechsstündigen Aufgabe geschah, wurde eine große Menge teurer Computerzeit verschwendet und der Zeitplan des gesamten Vorgangs wurde unterbrochen.



Storage Technologies schickte Techniker. Trotz aller Bemühungen konnten sie den Fehler unter Testbedingungen nicht reproduzieren: Es scheint, dass der Absturz mitten in großen Druckaufträgen auftrat. Das Problem war nicht die Hardware, sie ersetzten alles, was sie konnten: RAM, Mikrocontroller, Diskettenlaufwerk, jeden denkbaren Teil eines Bandlaufwerks - das Problem blieb bestehen.



Dann riefen die Techniker das Hauptquartier und den Experten an.



Der Prüfer schnappte sich einen Stuhl und eine Tasse Kaffee, setzte sich in den Computerraum - damals gab es spezielle Räume für Computer - und sah zu, wie das Personal einen großen Druckauftrag in die Warteschlange stellte. Der Experte wartete auf einen Fehler - und das geschah. Alle sahen den Experten an - und er hatte keine Ahnung, warum dies geschah. Daher befahl er, die Aufgabe erneut in die Warteschlange zu stellen, und alle Mitarbeiter mit Technikern kehrten zur Arbeit zurück.



Der Experte setzte sich wieder auf seinen Stuhl und wartete auf den Misserfolg. Es dauerte ungefähr sechs Stunden und der Fehler trat auf. Der Experte hatte wieder keine Ideen, außer dass alles in einem Raum voller Menschen passierte. Er befahl, die Mission neu zu starten, setzte sich wieder und wartete.



Bei der dritten Panne bemerkte der Experte etwas. Der Fehler trat auf, wenn das Personal die Riemen in einem externen Laufwerk wechselte. Darüber hinaus ereignete sich der Absturz, sobald einer der Mitarbeiter eine bestimmte Fliese auf dem Boden durchquerte.



Der Doppelboden bestand aus 6 bis 8 Zoll hohen Aluminiumfliesen. Unter dem Doppelboden verliefen zahlreiche Computerkabel, damit nicht versehentlich jemand auf ein wichtiges Kabel trat. Die Fliesen wurden sehr fest verlegt, damit keine Fremdkörper unter den Doppelboden gelangen konnten.



Der Experte stellte fest, dass eine der Fliesen verformt war. Wenn ein Mitarbeiter an die Ecke trat, rieb die Fliese ihre Kanten an benachbarten Fliesen. Sie rieben auch die Kunststoffteile, die die Fliesen verbanden, was zu statischen Mikroentladungen führte, die Hochfrequenzstörungen verursachten.



Heutzutage ist RAM viel besser vor Hochfrequenzstörungen geschützt. Aber in jenen Jahren war es nicht so. Der Experte stellte fest, dass diese Störungen den Speicher und damit den Betrieb des Betriebssystems störten. Er rief den Escortservice an, bestellte eine neue Fliese, installierte sie selbst und das Problem verschwand.



Es ist die Flut!



Die Geschichte spielte in einem Serverraum im vierten oder fünften Stock eines Büros in Portsmouth (glaube ich) im Hafenbereich.



Eines Tages stürzte ein Unix-Server mit der Hauptdatenbank ab. Er wurde neu gestartet, fiel aber freudig immer wieder hin. Wir haben uns entschlossen, jemanden vom Support anzurufen.



Support-Typ ... Ich glaube, er hieß Mark, aber das spielt keine Rolle ... Ich glaube nicht, dass ich ihn kenne. Es ist wirklich egal. Bleiben wir im Mark, okay? Ausgezeichnet.



Ein paar Stunden später kam Mark an (von Leeds nach Portsmouth ist der Weg nicht eng, wissen Sie), schaltete den Server ein und alles funktionierte ohne Probleme. Typische verdammte Unterstützung, der Kunde ist darüber sehr verärgert. Mark durchsucht die Protokolldateien und findet nichts Unangenehmes. Dann steigt Mark wieder in den Zug (oder was auch immer für ein Transportmittel er genommen hat, es könnte, soweit ich weiß, eine lahme Kuh gewesen sein ... nun, es spielt keine Rolle, okay?) Und fährt zurück nach Leeds, um den Tag zu verschwenden.



Der Server stürzt an diesem Abend erneut ab. Die Geschichte ist die gleiche ... der Server steigt nicht. Mark versucht, remote zu helfen, aber der Client kann den Server nicht starten.



Noch ein Zug, Bus, Zitronenbaiser oder eine andere Scheiße, und Mark ist zurück in Portsmouth. Schauen Sie, der Server startet ohne Probleme! Wunder. Mark überprüft mehrere Stunden lang, ob mit dem Betriebssystem oder der Software alles in Ordnung ist, und geht nach Leeds.



Gegen Mittag stürzt der Server ab (seien Sie ruhig!). Dieses Mal scheint es ratsam, den Hardware-Support hinzuzuziehen, um den Server zu ersetzen. Aber nein, nach ca. 10 Stunden fällt es auch.



Die Situation wiederholte sich mehrere Tage lang. Der Server ist in Betrieb, stürzt nach ca. 10 Stunden ab und startet die nächsten 2 Stunden nicht. Sie überprüften die Kühlung, Speicherlecks, sie überprüften alles, aber sie fanden nichts. Dann hörten die Abstürze auf.



Die Woche verging ohne Sorge ... alle waren glücklich. Glücklich, bis alles wieder anfängt. Das Bild ist das gleiche. 10 Stunden Arbeit, 2-3 Stunden Ausfallzeit ...



Und dann sagte jemand (ich glaube, sie sagten mir, dass diese Person nichts mit IT zu tun hat):



"Dies ist die Flut!"



Der Ausruf wurde mit leeren Blicken begrüßt, und wahrscheinlich schwankte jemandes Hand am Knopf, um den Wachmann anzurufen.



"Er hört auf mit der Flut zu arbeiten."



Dies scheint ein völlig fremdes Konzept für IT-Support-Mitarbeiter zu sein, die das Tide Yearbook kaum lesen, während sie sich zum Kaffee setzen. Sie erklärten, dass dies nichts mit der Flut zu tun habe, da der Server seit einer Woche ohne Probleme lief.



"Die Flut war letzte Woche niedrig und diese Woche hoch."



Ein bisschen Terminologie für diejenigen, die keine Lizenz zum Betreiben einer Yacht haben. Die Gezeiten hängen vom Mondzyklus ab. Und während sich die Erde dreht, erzeugt die Anziehungskraft von Sonne und Mond alle 12,5 Stunden eine Flutwelle. Zu Beginn eines 12,5-Stunden-Zyklus gibt es eine Flut, in der Mitte des Zyklus gibt es eine Ebbe und am Ende einer Flut wieder. Aber wenn sich die Umlaufbahn des Mondes ändert, ändert sich auch der Unterschied zwischen Ebbe und Flut. Wenn sich der Mond zwischen Sonne und Erde oder auf der gegenüberliegenden Seite der Erde befindet (Vollmond oder kein Mond), erhalten wir Syzygy-Gezeiten - die höchsten Gezeiten und die niedrigsten Ebben. Bei Halbmond bekommen wir Quadraturfluten - die niedrigsten Gezeiten. Der Unterschied zwischen den beiden Extremen ist stark reduziert. Der Mondzyklus dauert 28 Tage: Syzygy - Quadratur - Syzygy - Quadratur.



Als die Gezeitenkräfte den Technikern erklärt wurden, dachten sie sofort daran, die Polizei anzurufen. Und es ist ziemlich logisch. Aber es stellte sich heraus, dass der Typ Recht hatte. Zwei Wochen zuvor hatte ein Zerstörer in der Nähe des Büros angedockt. Jedes Mal, wenn die Flut es auf eine bestimmte Höhe anhob, befand sich der Radarposten des Schiffes auf der Höhe des Bodens des Serverraums. Und Radar (oder elektronische Kriegsausrüstung oder ein anderes Spielzeug des Militärs) verursachte Chaos in Computern.



Flugmission für eine Rakete



Ich wurde angewiesen, ein großes Raketenstart-Kontroll- und Überwachungssystem (ca. 400.000 Zeilen) für neue Versionen des Betriebssystems, des Compilers und der Sprache zu portieren. Genauer gesagt, von Solaris 2.5.1 unter Solaris 7 und von Verdix Ada Development System (VADS) in Ada 83 bis Rational Apex Ada System in Ada 95. VADS wurde von Rational gekauft und sein Produkt ist veraltet, obwohl Rational Es wurde versucht, kompatible Versionen von VADS-spezifischen Paketen zu implementieren, um den Übergang zum Apex-Compiler zu erleichtern.



Drei Leute haben mir geholfen, nur sauber kompilierten Code zu bekommen. Es dauerte zwei Wochen. Und dann habe ich alleine gearbeitet, um das System zum Laufen zu bringen. Kurz gesagt, es war die schlechteste Architektur und Implementierung eines Softwaresystems, die mir jemals begegnet ist. Daher dauerte es weitere zwei Monate, bis die Portierung abgeschlossen war. Dann wurde das System zum Testen übergeben, was mehrere Monate dauerte. Ich habe die Fehler, die ich beim Testen gefunden habe, sofort behoben, aber ihre Anzahl hat schnell abgenommen (der Quellcode war ein Produktionssystem, daher funktionierte seine Funktionalität ziemlich zuverlässig, ich musste nur die Fehler entfernen, die bei der Anpassung an den neuen Compiler auftraten). Am Ende, als alles so funktionierte, wie es sollte, wurde ich zu einem anderen Projekt versetzt.



Und am Freitag vor Thanksgiving klingelte das Telefon.



Ungefähr drei Wochen später sollte ein Raketenstart getestet werden, und in Labortests des Countdowns wurde die Befehlssequenz blockiert. Im wirklichen Leben würde dies zu einer Unterbrechung der Prüfung führen. Wenn innerhalb weniger Sekunden nach dem Starten des Motors eine Blockierung auftritt, treten in den Hilfssystemen mehrere irreversible Aktionen auf, deren Vorbereitung der Rakete lange und teuer dauern würde. Es würde nicht anfangen, aber viele Leute würden sich sehr über den Zeitverlust und das sehr, sehr große Geld aufregen. Lassen Sie sich von niemandem sagen, dass das Verteidigungsministerium kurzerhand Geld ausgibt - ich habe noch keinen einzigen Vertragsmanager getroffen, dessen Budget nicht das erste oder zweite ist, gefolgt von einem Zeitplan.



In den vergangenen Monaten wurde dieser Countdown-Test in vielen Variationen hunderte Male mit nur wenigen kleinen Problemen durchgeführt. Die Wahrscheinlichkeit dafür war also sehr gering, aber die Konsequenzen waren sehr bedeutend. Multiplizieren Sie diese beiden Faktoren, und Sie werden verstehen, dass die Nachrichten eine ruinierte Ferienwoche für mich und Dutzende von Ingenieuren und Managern vorhersagten.



Und die Aufmerksamkeit wurde auf mich als die Person gelenkt, die das System portiert hat.



Wie bei den meisten sicherheitskritischen Systemen wurden hier viele Parameter protokolliert, sodass es ziemlich einfach war, die wenigen Codezeilen zu identifizieren, die ausgeführt wurden, bevor das System abstürzte. Und natürlich war absolut nichts Außergewöhnliches an ihnen, dieselben Ausdrücke wurden buchstäblich tausende Male während desselben Laufs erfolgreich ausgeführt.



Wir haben die Leute von Apex nach Rational gerufen, weil sie den Compiler entwickelt hatten und einige der Routinen, die sie entwickelt hatten, im verdächtigen Code aufgerufen wurden. Sie (und alle anderen) waren beeindruckt von der Notwendigkeit, die Ursache des Problems von buchstäblich nationaler Bedeutung herauszufinden.



Da die Protokolle nichts Interessantes enthielten, beschlossen wir, das Problem in einem örtlichen Labor zu reproduzieren. Dies war keine leichte Aufgabe, da das Ereignis ungefähr alle 1000 Läufe auftrat. Einer der vermeintlichen Gründe war, dass der Aufruf einer vom Hersteller entwickelten Mutex-Funktion (Teil des VADS-Migrationsstapels)Unlockführte nicht zum Entsperren. Der aufrufende Thread verarbeitete Heartbeat-Nachrichten, die nominell jede Sekunde eintrafen. Wir haben die Frequenz auf 10 Hz erhöht, dh 10 Mal pro Sekunde, und haben angefangen zu laufen. Nach ungefähr einer Stunde war das System gesperrt. Im Protokoll haben wir gesehen, dass die Reihenfolge der aufgezeichneten Nachrichten dieselbe war wie während des fehlgeschlagenen Tests. Wir machten noch ein paar Läufe, das System wurde 45-90 Minuten nach dem Start stabil blockiert und jedes Mal hatte das Protokoll die gleiche Spur. Obwohl wir jetzt technisch unterschiedlichen Code ausführten - die Nachrichtenrate war unterschiedlich -, wurde das Verhalten des Systems wiederholt, sodass wir sicherstellten, dass dieses Ladeszenario zu demselben Problem führte.



Nun musste genau herausgefunden werden, wo in der Reihenfolge der Ausdrücke die Blockierung auftrat.



Diese Implementierung verwendete das Ada-Task-System und wurde unglaublich schlecht verwendet. Aufgaben sind ein übergeordnetes, gleichzeitig ausführbares Konstrukt in Ada, ähnlich wie Ausführungsthreads, die nur in die Sprache selbst integriert sind. Wenn zwei Aufgaben interagieren müssen, "treffen" sie sich, tauschen die erforderlichen Daten aus, stoppen das Rendezvous und kehren zu ihren unabhängigen Leistungen zurück. Das System wurde jedoch anders implementiert. Nachdem das Ziel ein Rendezvous hatte, traf sich dieses Ziel mit dem anderen, das sich dann mit dem dritten traf, und so weiter, bis eine gewisse Verarbeitung abgeschlossen war. Danach endeten alle diese Rendezvous und jede Aufgabe musste zu ihrer Ausführung zurückkehren. Das heißt, wir hatten es mit dem teuersten Funktionsaufrufsystem der Welt zu tun.Dadurch wurde der gesamte "Multitasking" -Prozess angehalten, während einige der Eingabedaten verarbeitet wurden. Und vorher führte dies nicht zu Problemen, nur weil der Durchsatz sehr gering war.



Ich habe diesen Taskmechanismus beschrieben, da ein "Taskwechsel" auftreten kann, wenn ein Rendezvous angefordert wird oder voraussichtlich abgeschlossen wird. Das heißt, der Prozessor könnte mit der Verarbeitung einer anderen Aufgabe beginnen, die zur Ausführung bereit ist. Es stellt sich heraus, dass, wenn eine Aufgabe zum Rendezvous mit einer anderen Aufgabe bereit ist, die Ausführung einer völlig anderen Aufgabe beginnen kann und die Steuerung schließlich zum ersten Rendezvous zurückkehrt. Es können auch andere Ereignisse auftreten, die zu einem Taskwechsel führen. Ein solches Ereignis ist ein Systemfunktionsaufruf, beispielsweise das Drucken oder Ausführen eines Mutex.



Um zu verstehen, welche Codezeile das Problem verursacht hat, musste ich einen Weg finden, um den Fortschritt der Ausdrucksfolge aufzuzeichnen, ohne einen Taskwechsel auszulösen, der das Auftreten des Absturzes verhindern könnte. Also konnte ich nicht ausnutzenPut_Line()um E / A-Operationen zu vermeiden. Sie könnten eine Zählervariable oder ähnliches festlegen, aber wie kann ich ihren Wert sehen, wenn ich ihn nicht auf dem Bildschirm anzeigen kann?



Bei der Untersuchung des Protokolls stellte sich außerdem heraus, dass trotz des Einfrierens der Verarbeitung von Heartbeat-Nachrichten, die alle E / A-Vorgänge des Prozesses blockierten und keine andere Verarbeitung zuließen, andere unabhängige Aufgaben weiterhin ausgeführt wurden. Das heißt, die Arbeit wurde nicht vollständig blockiert, sondern nur die (kritische) Aufgabenkette.



Dies war der Haken, der erforderlich war, um den blockierenden Ausdruck zu bewerten.



Ich habe ein Ada-Paket erstellt, das eine Aufgabe, einen Aufzählungstyp und eine globale Variable dieses Typs enthielt. Aufgezählt wurden Literale auf spezifische Ausdrücke problematische Sequenzen gebunden (z Incrementing_Buffer_Index, Locking_Mutex,Mutex_Unlocked) und fügte dann Zuweisungsausdrücke ein, die einer globalen Variablen die entsprechende Aufzählung zuwiesen. Da der Objektcode all dessen einfach konstant im Speicher blieb, war ein Taskwechsel aufgrund seiner Ausführung äußerst unwahrscheinlich. Zunächst vermuteten wir Ausdrücke, die die Aufgabe wechseln könnten, da die Blockierung während der Ausführung auftrat und beim Zurückschalten der Aufgabe (aus mehreren Gründen) nicht zurückkehrte.



Die Verfolgungsaufgabe wurde einfach in einer Schleife ausgeführt und regelmäßig überprüft, ob sich der Wert der globalen Variablen geändert hat. Bei jeder Änderung wurde der Wert in einer Datei gespeichert. Dann eine kurze Wartezeit und ein neuer Scheck. Ich habe die Variable in eine Datei geschrieben, da die Aufgabe nur ausgeführt wurde, als das System sie beim Wechseln der Aufgabe im Problembereich zur Ausführung auswählte. Was auch immer in dieser Aufgabe passiert, hat keine Auswirkungen auf andere nicht verwandte gesperrte Aufgaben.



Es wurde erwartet, dass die globale Variable bei jedem nächsten Ausdruck zurückgesetzt wird, wenn das System die Ausführung des problematischen Codes erreicht. Dann passiert etwas, was zu einem Wechsel der Aufgabe führt, und da die Häufigkeit ihrer Ausführung (10 Hz) niedriger als die der Überwachungsaufgabe ist, könnte der Monitor den Wert der globalen Variablen festlegen und schreiben. In einer normalen Situation könnte ich eine sich wiederholende Folge einer Teilmenge von Aufzählungen erhalten: die letzten Werte der Variablen zum Zeitpunkt des Taskwechsels. Beim Hängen sollte sich die globale Variable nicht mehr ändern, und der zuletzt geschriebene Wert zeigt an, welcher Ausdruck die Ausführung nicht abgeschlossen hat.



Den Tracking-Code gestartet. Es ist gefroren. Und die Überwachung funktionierte wie am Schnürchen.



Das Protokoll endete mit der erwarteten Sequenz, die durch einen Wert unterbrochen wurde, der angibt, dass der Mutex aufgerufen wurde Unlockund die Aufgabe ansteht - wie dies bei Tausenden von vorherigen Aufrufen der Fall war.



Zu diesem Zeitpunkt analysierten die Apex-Ingenieure verzweifelt ihren Code und fanden einen Platz im Mutex, an dem theoretisch eine Sperre auftreten könnte. Die Wahrscheinlichkeit war jedoch sehr gering, da nur eine bestimmte Folge von Ereignissen zu einem bestimmten Zeitpunkt zu einer Blockade führen konnte. Murphys Gesetzesjungen, es ist Murphys Gesetz.



Um diesen Code zu schützen, habe ich die Aufrufe der Mutex-Funktionen (die auf der Mutex-Funktionalität des Betriebssystems basieren) durch ein kleines natives Ada-Mutex-Paket ersetzt, um den Mutex-Zugriff auf diesen Code zu steuern.



Fügte es in den Code ein und führte den Test aus. Sieben Stunden später funktionierte der Code weiter.



Mein Code wurde an Rational übertragen, wo er kompiliert, zerlegt und überprüft wurde, dass er nicht denselben Ansatz verwendet, der in den problematischen Mutex-Funktionen verwendet wurde.



Es war die überfüllteste Codeüberprüfung in meiner Karriere :) Es waren ungefähr zehn Ingenieure und Manager mit mir im Raum, ein Dutzend weitere Personen, die über eine Telefonkonferenz verbunden waren - und alle untersuchten ungefähr 20 Codezeilen.



Der Code wurde überprüft, neue ausführbare Dateien wurden erstellt und für formale Regressionstests eingereicht. Ein paar Wochen später waren die Countdown-Tests erfolgreich und die Rakete startete.



Okay, das ist alles gut und schön, aber worum geht es in dieser Geschichte?



Es war ein total widerliches Problem. Hunderttausende von Codezeilen, parallele Ausführung, über ein Dutzend interagierende Prozesse, schlechte Architektur und Implementierung, Schnittstellen für eingebettete Systeme und Millionen von Dollar. Kein Druck, richtig.



Ich war nicht der einzige, der an diesem Problem arbeitete, obwohl ich bei der Portierung im Rampenlicht stand. Aber obwohl ich es getan habe, bedeutet dies nicht, dass ich alle hunderttausenden Codezeilen verstanden oder zumindest durchgesehen habe. Der Code und die Protokolle wurden von Ingenieuren im ganzen Land analysiert, aber als sie mir ihre Hypothesen über die Gründe für den Fehler erzählten, brauchte ich eine halbe Minute, um sie zu widerlegen. Und als ich gebeten wurde, Theorien zu analysieren, gab ich sie an jemand anderen weiter, weil mir klar war, dass diese Ingenieure den falschen Weg gingen. Klang anmaßend? Ja, aber ich habe Hypothesen und Anfragen aus einem anderen Grund abgelehnt.



Ich habe die Natur des Problems verstanden. Ich wusste nicht genau, wo es war oder warum, aber ich wusste genau, was los war.



Im Laufe der Jahre habe ich viel Wissen und Erfahrung gesammelt. Ich war einer der Pioniere bei der Verwendung von Ada und habe die Vor- und Nachteile verstanden. Ich weiß, wie die Ada-Laufzeitbibliotheken Aufgaben behandeln und mit der parallelen Ausführung umgehen. Und ich bin gut in Low-Level-Programmierung auf der Ebene von Speicher, Registern und Assembler. Mit anderen Worten, ich habe tiefes Wissen auf meinem Gebiet. Und ich habe sie benutzt, um die Ursache des Problems zu finden. Ich habe den Fehler nicht nur umgangen, sondern auch herausgefunden, wie ich ihn in einer sehr sensiblen Ausführungsumgebung finden kann.



Solche Geschichten über den Kampf mit dem Code sind für diejenigen, die mit den Besonderheiten und Bedingungen eines solchen Kampfes nicht vertraut sind, nicht sehr interessant. Aber diese Geschichten helfen zu verstehen, was es braucht, um wirklich schwierige Probleme zu lösen.



Sie müssen mehr als nur ein Programmierer sein, um wirklich schwierige Probleme zu lösen. Sie müssen das "Schicksal" des Codes verstehen, wie er mit seiner Umgebung interagiert und wie die Umgebung selbst funktioniert.



Und dann haben Sie Ihre verwöhnte Ferienwoche.






Fortsetzung folgt.



All Articles