Λαογραφία προγραμματιστών και μηχανικών (μέρος 1)

Λαογραφία προγραμματιστών και μηχανικών (μέρος 1)

Αυτή είναι μια επιλογή από ιστορίες από το Διαδίκτυο για το πώς τα σφάλματα μερικές φορές έχουν εντελώς απίστευτες εκδηλώσεις. Ίσως έχετε κάτι να πείτε κι εσείς.

Αλλεργία αυτοκινήτου στο παγωτό βανίλια

Μια ιστορία για μηχανικούς που καταλαβαίνουν ότι το προφανές δεν είναι πάντα η απάντηση, και ότι όσο μακρινό κι αν φαίνονται τα γεγονότα, εξακολουθούν να είναι τα γεγονότα. Το τμήμα Pontiac της General Motors Corporation έλαβε μια καταγγελία:

Είναι η δεύτερη φορά που σου γράφω και δεν σε κατηγορώ που δεν απαντάς, γιατί ακούγεται τρελό. Η οικογένειά μας έχει την παράδοση να τρώει παγωτό κάθε βράδυ μετά το δείπνο. Τα είδη του παγωτού αλλάζουν κάθε φορά και μετά το δείπνο όλη η οικογένεια επιλέγει ποιο παγωτό θα αγοράσει και μετά πηγαίνω στο κατάστημα. Πρόσφατα αγόρασα ένα νέο Pontiac και από τότε τα ταξίδια μου για να πάρω παγωτό έχουν γίνει πρόβλημα. Βλέπεις, κάθε φορά που αγοράζω παγωτό βανίλια και επιστρέφω από το κατάστημα, το αυτοκίνητο δεν ξεκινάει. Αν φέρω άλλο παγωτό, το αυτοκίνητο ξεκινά χωρίς πρόβλημα. Θέλω να κάνω μια σοβαρή ερώτηση, όσο ανόητο κι αν ακούγεται: «Τι είναι αυτό με το Pontiac που το κάνει να μην ξεκινά όταν φέρνω παγωτό βανίλια, αλλά ξεκινάει εύκολα όταν φέρνω άλλη γεύση παγωτού;»

Όπως μπορείτε να φανταστείτε, ο πρόεδρος του τμήματος ήταν δύσπιστος σχετικά με την επιστολή. Ωστόσο, για κάθε ενδεχόμενο, έστειλα μηχανικό να ελέγξει. Έμεινε έκπληκτος που τον συνάντησε ένας πλούσιος, καλά μορφωμένος άντρας που ζούσε σε μια όμορφη περιοχή. Συμφώνησαν να συναντηθούν αμέσως μετά το δείπνο για να πάνε οι δυο τους στο μαγαζί για παγωτό. Εκείνο το βράδυ ήταν βανίλια, και όταν επέστρεψαν στο αυτοκίνητο, δεν ξεκινούσε.

Ο μηχανικός ήρθε άλλα τρία βράδια. Την πρώτη φορά το παγωτό ήταν σοκολάτα. Το αυτοκίνητο ξεκίνησε. Τη δεύτερη φορά υπήρχε παγωτό φράουλα. Το αυτοκίνητο ξεκίνησε. Το τρίτο βράδυ ζήτησε να πάρει βανίλια. Το αυτοκίνητο δεν ξεκίνησε.

Συλλογιζόμενος ορθολογικά, ο μηχανικός αρνήθηκε να πιστέψει ότι το αυτοκίνητο ήταν αλλεργικό στο παγωτό βανίλια. Ως εκ τούτου, συμφώνησα με τον ιδιοκτήτη του αυτοκινήτου ότι θα συνεχίσει τις επισκέψεις του μέχρι να βρει λύση στο πρόβλημα. Και στην πορεία, άρχισε να κρατάει σημειώσεις: έγραψε όλες τις πληροφορίες, την ώρα της ημέρας, τον τύπο της βενζίνης, την ώρα άφιξης και επιστροφής από το κατάστημα κ.λπ.

Ο μηχανικός σύντομα συνειδητοποίησε ότι ο ιδιοκτήτης του αυτοκινήτου ξόδεψε λιγότερο χρόνο αγοράζοντας παγωτό βανίλια. Ο λόγος ήταν η διάταξη των εμπορευμάτων στο κατάστημα. Το παγωτό βανίλια ήταν το πιο δημοφιλές και φυλάσσονταν σε ξεχωριστή κατάψυξη στο μπροστινό μέρος του καταστήματος για να είναι ευκολότερο να το βρεις. Και όλες οι άλλες ποικιλίες ήταν στο πίσω μέρος του καταστήματος και χρειάστηκε πολύ περισσότερος χρόνος για να βρεθεί η σωστή ποικιλία και να πληρωθεί.

Τώρα το ερώτημα ήταν για τον μηχανικό: γιατί δεν ξεκίνησε το αυτοκίνητο αν είχε περάσει λιγότερος χρόνος από τη στιγμή που σβήστηκε ο κινητήρας; Επειδή το πρόβλημα ήταν ο χρόνος, όχι το παγωτό βανίλια, ο μηχανικός βρήκε γρήγορα την απάντηση: ήταν μια κλειδαριά αερίου. Συνέβαινε κάθε βράδυ, αλλά όταν ο ιδιοκτήτης του αυτοκινήτου αφιερώνει περισσότερο χρόνο ψάχνοντας για παγωτό, ο κινητήρας κατάφερε να κρυώσει αρκετά και να τεθεί σε λειτουργία εύκολα. Και όταν ο άντρας αγόρασε παγωτό βανίλια, ο κινητήρας ήταν ακόμα πολύ ζεστός και η κλειδαριά αερίου δεν είχε χρόνο να διαλυθεί.

Ηθικό: Ακόμα και εντελώς τρελά προβλήματα μερικές φορές είναι αληθινά.

Crash Bandicoot

Είναι οδυνηρό να το βιώνεις αυτό. Ως προγραμματιστής, συνηθίζεις να κατηγορείς τον κώδικά σου πρώτος, δεύτερος, τρίτος... και κάπου στη δέκατη χιλιάδα κατηγορείς τον μεταγλωττιστή. Και πιο κάτω στη λίστα κατηγορείτε ήδη τον εξοπλισμό.

Εδώ είναι η ιστορία μου για το σφάλμα υλικού.

Για το παιχνίδι Crash Bandicoot, έγραψα κώδικα για φόρτωση και αποθήκευση σε κάρτα μνήμης. Για έναν τόσο αυτάρεσκο προγραμματιστή παιχνιδιών, ήταν σαν μια βόλτα στο πάρκο: νόμιζα ότι η δουλειά θα διαρκούσε αρκετές μέρες. Ωστόσο, κατέληξα να διορθώνω τον κώδικα για έξι εβδομάδες. Στην πορεία έλυσα άλλα προβλήματα, αλλά κάθε λίγες μέρες επέστρεφα σε αυτόν τον κωδικό για μερικές ώρες. Ήταν αγωνία.

Το σύμπτωμα έμοιαζε ως εξής: όταν αποθηκεύετε την τρέχουσα ροή του παιχνιδιού και αποκτάτε πρόσβαση στην κάρτα μνήμης, όλα σχεδόν πάντα πάνε καλά... Αλλά μερικές φορές η λειτουργία ανάγνωσης ή εγγραφής λήγει χωρίς προφανή λόγο. Μια σύντομη εγγραφή συχνά βλάπτει την κάρτα μνήμης. Όταν ένας παίκτης προσπαθεί να σώσει, όχι μόνο αποτυγχάνει να σώσει, αλλά καταστρέφει και τον χάρτη. Σκατά.

Μετά από λίγο, ο παραγωγός μας στη Sony, Connie Bus, άρχισε να πανικοβάλλεται. Δεν μπορούσαμε να στείλουμε το παιχνίδι με αυτό το σφάλμα και έξι εβδομάδες αργότερα δεν κατάλαβα τι προκαλούσε το πρόβλημα. Μέσω της Connie, επικοινωνήσαμε με άλλους προγραμματιστές του PS1: έχει συναντήσει κανείς κάτι παρόμοιο; Οχι. Κανείς δεν είχε πρόβλημα με την κάρτα μνήμης.

Όταν δεν έχετε ιδέες για τον εντοπισμό σφαλμάτων, η μόνη προσέγγιση που απομένει είναι να «διαίρετε και βασίλευε»: αφαιρέστε όλο και περισσότερο κώδικα από το ελαττωματικό πρόγραμμα μέχρι να μείνει ένα σχετικά μικρό κομμάτι που εξακολουθεί να προκαλεί το πρόβλημα. Δηλαδή κόβεις κομμάτι κομμάτι το πρόγραμμα μέχρι να παραμείνει το τμήμα που περιέχει το bug.

Αλλά το θέμα είναι ότι είναι πολύ δύσκολο να κόψεις κομμάτια από ένα βιντεοπαιχνίδι. Πώς να το εκτελέσετε εάν αφαιρέσατε τον κωδικό που προσομοιώνει τη βαρύτητα; Ή σχεδιάζοντας χαρακτήρες;

Επομένως, πρέπει να αντικαταστήσουμε ολόκληρες ενότητες με στελέχη που προσποιούνται ότι κάνουν κάτι χρήσιμο, αλλά στην πραγματικότητα κάνουν κάτι πολύ απλό που δεν μπορεί να περιέχει σφάλματα. Πρέπει να γράψουμε τέτοια δεκανίκια για να δουλέψει τουλάχιστον το παιχνίδι. Αυτή είναι μια αργή και επίπονη διαδικασία.

Με λίγα λόγια, το έκανα. Αφαίρεσα όλο και περισσότερα κομμάτια κώδικα μέχρι να μου μείνει ο αρχικός κώδικας που ρυθμίζει το σύστημα για να τρέξει το παιχνίδι, αρχικοποιεί το υλικό απόδοσης κ.λπ. Φυσικά, σε αυτό το στάδιο δεν μπορούσα να δημιουργήσω ένα μενού αποθήκευσης και φόρτωσης, γιατί θα έπρεπε να δημιουργήσω ένα στέλεχος για όλο τον κώδικα γραφικών. Αλλά θα μπορούσα να προσποιηθώ ότι είμαι χρήστης χρησιμοποιώντας την (αόρατη) οθόνη αποθήκευσης και φόρτωσης και να ζητήσω να γίνει αποθήκευση και μετά να γράψω στην κάρτα μνήμης.

Αυτό μου άφησε ένα μικρό κομμάτι κώδικα που είχε ακόμα το παραπάνω πρόβλημα - αλλά συνέβαινε τυχαία! Τις περισσότερες φορές όλα λειτουργούσαν καλά, αλλά περιστασιακά υπήρχαν δυσλειτουργίες. Αφαίρεσα σχεδόν όλο τον κωδικό του παιχνιδιού, αλλά το σφάλμα ήταν ακόμα ζωντανό. Αυτό ήταν μπερδεμένο: ο κωδικός που απομένει στην πραγματικότητα δεν έκανε τίποτα.

Κάποια στιγμή, μάλλον γύρω στις τρεις το πρωί, μου ήρθε μια σκέψη. Οι λειτουργίες ανάγνωσης και εγγραφής (εισόδου/εξόδου) περιλαμβάνουν ακριβείς χρόνους εκτέλεσης. Όταν εργάζεστε με σκληρό δίσκο, κάρτα μνήμης ή μονάδα Bluetooth, ο κωδικός χαμηλού επιπέδου που είναι υπεύθυνος για την ανάγνωση και τη γραφή το κάνει σύμφωνα με τους παλμούς ρολογιού.

Με τη βοήθεια ενός ρολογιού, μια συσκευή που δεν είναι απευθείας συνδεδεμένη με τον επεξεργαστή συγχρονίζεται με τον κώδικα που εκτελείται στον επεξεργαστή. Το ρολόι καθορίζει τον ρυθμό baud—την ταχύτητα με την οποία μεταφέρονται τα δεδομένα. Εάν υπάρχει σύγχυση με τους χρονισμούς, τότε είτε το υλικό είτε το λογισμικό, είτε και τα δύο, επίσης μπερδεύονται. Και αυτό είναι πολύ κακό, γιατί τα δεδομένα μπορεί να καταστραφούν.

Τι γίνεται αν κάτι στον κώδικά μας μπερδεύει τους χρονισμούς; Έλεγξα όλα όσα σχετίζονται με αυτό στον κώδικα του προγράμματος δοκιμής και παρατήρησα ότι ρυθμίσαμε το προγραμματιζόμενο χρονόμετρο στο PS1 στο 1 kHz (1000 ticks ανά δευτερόλεπτο). Αυτό είναι αρκετά· από προεπιλογή, όταν ξεκινά η κονσόλα, τρέχει στα 100 Hz. Και τα περισσότερα παιχνίδια χρησιμοποιούν αυτή τη συχνότητα.

Ο Andy, ο προγραμματιστής του παιχνιδιού, ρύθμισε το χρονόμετρο στο 1 kHz, έτσι ώστε οι κινήσεις να υπολογίζονται με μεγαλύτερη ακρίβεια. Ο Andy τείνει να υπερβαίνει τη θάλασσα και αν μιμούμε τη βαρύτητα, το κάνουμε όσο το δυνατόν ακριβέστερα!

Τι θα γινόταν όμως αν η επιτάχυνση του χρονοδιακόπτη επηρέαζε κατά κάποιο τρόπο τον συνολικό χρόνο του προγράμματος και συνεπώς το ρολόι που ρυθμίζει τον ρυθμό baud για την κάρτα μνήμης;

Σχολίασα τον κωδικό του χρονοδιακόπτη. Το λάθος δεν συνέβη ξανά. Αυτό όμως δεν σημαίνει ότι το διορθώσαμε, γιατί η αστοχία προέκυψε τυχαία. Κι αν ήμουν απλά τυχερός;

Λίγες μέρες αργότερα πειραματίστηκα ξανά με το πρόγραμμα δοκιμών. Το σφάλμα δεν επανεμφανίστηκε. Επέστρεψα στην πλήρη βάση κωδικών του παιχνιδιού και τροποποίησα τον κωδικό αποθήκευσης και φόρτωσης έτσι ώστε ο προγραμματιζόμενος χρονοδιακόπτης να επανέλθει στην αρχική του τιμή (100 Hz) πριν αποκτήσει πρόσβαση στην κάρτα μνήμης και, στη συνέχεια, να επανέλθει στο 1 kHz. Δεν υπήρξαν άλλες συντριβές.

Γιατί όμως συνέβη αυτό;

Επέστρεψα ξανά στο πρόγραμμα δοκιμών. Προσπάθησα να βρω κάποιο μοτίβο στην εμφάνιση σφάλματος με ένα χρονόμετρο 1 kHz. Τελικά παρατήρησα ότι το σφάλμα παρουσιάζεται όταν κάποιος παίζει με ένα χειριστήριο PS1. Επειδή σπάνια θα το έκανα αυτό μόνος μου - γιατί θα χρειαζόμουν έναν ελεγκτή κατά τη δοκιμή του κωδικού αποθήκευσης και φόρτωσης; - Δεν παρατήρησα καν αυτή την εξάρτηση. Αλλά μια μέρα ένας από τους καλλιτέχνες μας περίμενε να τελειώσω τις δοκιμές -μάλλον έβρισα εκείνη τη στιγμή- και στριφογύρισε νευρικά το χειριστήριο στα χέρια του. Παρουσιάστηκε σφάλμα. "ΟΠΑ, τι?!" Λοιπόν, κάντε το ξανά!»

Όταν συνειδητοποίησα ότι αυτά τα δύο συμβάντα ήταν αλληλένδετα, μπόρεσα να αναπαράγω εύκολα το σφάλμα: άρχισα την εγγραφή στην κάρτα μνήμης, μετακίνησα το χειριστήριο και κατέστρεψα την κάρτα μνήμης. Εμένα μου φαινόταν σαν ένα σφάλμα υλικού.

Ήρθα στην Κόνι και της είπα για την ανακάλυψή μου. Μετέφερε τις πληροφορίες σε έναν από τους μηχανικούς που σχεδίασαν το PS1. «Αδύνατον», απάντησε, «Δεν μπορεί να είναι πρόβλημα υλικού». Ζήτησα από την Κόνι να κανονίσει μια συζήτηση για εμάς.

Με πήρε τηλέφωνο ο μηχανικός και μαλώσαμε με τα σπασμένα αγγλικά του και τα (εξαιρετικά) σπασμένα γιαπωνέζικα μου. Τελικά είπα, "Επιτρέψτε μου να στείλω το δοκιμαστικό πρόγραμμα 30 γραμμών όπου η μετακίνηση του ελεγκτή προκαλεί σφάλμα." Συμφώνησε. Είπε ότι ήταν χάσιμο χρόνου και ότι ήταν τρομερά απασχολημένος με τη δουλειά σε ένα νέο έργο, αλλά θα ενέδιδε γιατί ήμασταν ένας πολύ σημαντικός προγραμματιστής για τη Sony. Καθάρισα το δοκιμαστικό μου πρόγραμμα και του το έστειλα.

Το επόμενο βράδυ (ήμασταν στο Λος Άντζελες και εκείνος στο Τόκιο) με πήρε τηλέφωνο και μου ζήτησε συγγνώμη. Ήταν πρόβλημα υλικού.

Δεν ξέρω ποιο ακριβώς ήταν το σφάλμα, αλλά από ό,τι άκουσα στα κεντρικά γραφεία της Sony, αν ρυθμίσετε το χρονόμετρο σε αρκετά υψηλή τιμή, παρενέβαινε σε εξαρτήματα της μητρικής πλακέτας κοντά στον κρύσταλλο του χρονοδιακόπτη. Ένα από αυτά ήταν ένας ελεγκτής ρυθμού baud για την κάρτα μνήμης, ο οποίος όριζε επίσης τον ρυθμό baud για τους ελεγκτές. Δεν είμαι μηχανικός, οπότε μπορεί να έχω μπλέξει κάτι.

Αλλά η ουσία είναι ότι υπήρχαν παρεμβολές μεταξύ εξαρτημάτων στη μητρική πλακέτα. Και κατά τη μετάδοση δεδομένων ταυτόχρονα μέσω της θύρας του ελεγκτή και της θύρας της κάρτας μνήμης με χρονοδιακόπτη που λειτουργεί στο 1 kHz, χάθηκαν bits, χάθηκαν δεδομένα και η κάρτα υπέστη ζημιά.

Κακές αγελάδες

Στη δεκαετία του 1980, ο μέντοράς μου Σεργκέι έγραψε λογισμικό για το SM-1800, έναν σοβιετικό κλώνο του PDP-11. Αυτός ο μικροϋπολογιστής μόλις εγκαταστάθηκε σε έναν σιδηροδρομικό σταθμό κοντά στο Sverdlovsk, έναν σημαντικό κόμβο μεταφορών στην ΕΣΣΔ. Το νέο σύστημα σχεδιάστηκε για να δρομολογεί βαγόνια και εμπορευματική κυκλοφορία. Αλλά περιείχε ένα ενοχλητικό σφάλμα που οδήγησε σε τυχαία σφάλματα και συντριβές. Πτώσεις συνέβαιναν πάντα όταν κάποιος πήγαινε σπίτι το βράδυ. Όμως, παρά την ενδελεχή έρευνα την επόμενη μέρα, ο υπολογιστής λειτούργησε σωστά σε όλα τα χειροκίνητα και αυτόματα τεστ. Αυτό συνήθως υποδεικνύει μια κατάσταση αγώνα ή κάποιο άλλο ανταγωνιστικό σφάλμα που εμφανίζεται υπό ορισμένες συνθήκες. Κουρασμένος από τις κλήσεις αργά το βράδυ, ο Σεργκέι αποφάσισε να φτάσει στο κάτω μέρος και πρώτα απ 'όλα, να καταλάβει ποιες συνθήκες στην αυλή μάρσαλινγκ οδήγησαν σε βλάβη του υπολογιστή.

Αρχικά, συνέλεξε στατιστικά για όλες τις ανεξήγητες πτώσεις και δημιούργησε ένα γράφημα ανά ημερομηνία και ώρα. Το μοτίβο ήταν προφανές. Αφού παρατήρησε για μερικές ακόμη ημέρες, ο Σεργκέι συνειδητοποίησε ότι μπορούσε εύκολα να προβλέψει την ώρα των μελλοντικών αποτυχιών του συστήματος.

Σύντομα έμαθε ότι διαταραχές σημειώθηκαν μόνο όταν ο σταθμός διαλογούσε φορτία τρένων με βοοειδή από τη βόρεια Ουκρανία και τη δυτική Ρωσία που κατευθύνονταν σε ένα κοντινό σφαγείο. Αυτό από μόνο του ήταν περίεργο, γιατί το σφαγείο προμηθεύονταν από φάρμες που βρίσκονταν πολύ πιο κοντά, στο Καζακστάν.

Το πυρηνικό εργοστάσιο του Τσερνομπίλ εξερράγη το 1986 και οι ραδιενεργές επιπτώσεις κατέστησαν τις γύρω περιοχές ακατοίκητες. Τεράστιες περιοχές στη βόρεια Ουκρανία, τη Λευκορωσία και τη δυτική Ρωσία μολύνθηκαν. Υποψιαζόμενος υψηλά επίπεδα ακτινοβολίας στα βαγόνια που έφταναν, ο Σεργκέι ανέπτυξε μια μέθοδο για να δοκιμάσει αυτή τη θεωρία. Απαγορεύτηκε στον πληθυσμό να έχει δοσίμετρα, έτσι ο Σεργκέι εγγράφηκε με αρκετούς στρατιωτικούς στο σιδηροδρομικό σταθμό. Μετά από πολλά ποτά βότκας, κατάφερε να πείσει έναν στρατιώτη να μετρήσει το επίπεδο ακτινοβολίας σε ένα από τα ύποπτα βαγόνια. Αποδείχθηκε ότι το επίπεδο ήταν αρκετές φορές υψηλότερο από τις κανονικές τιμές.

Όχι μόνο τα βοοειδή εξέπεμπαν πολλή ακτινοβολία, αλλά το επίπεδό του ήταν τόσο υψηλό που οδήγησε σε τυχαία απώλεια κομματιών στη μνήμη του SM-1800, το οποίο βρισκόταν σε ένα κτίριο δίπλα στον σταθμό.

Υπήρχε έλλειψη τροφίμων στην ΕΣΣΔ και οι αρχές αποφάσισαν να αναμίξουν το κρέας του Τσερνομπίλ με κρέας από άλλες περιοχές της χώρας. Αυτό κατέστησε δυνατή τη μείωση του συνολικού επιπέδου ραδιενέργειας χωρίς απώλεια πολύτιμων πόρων. Έχοντας μάθει για αυτό, ο Σεργκέι συμπλήρωσε αμέσως έγγραφα για μετανάστευση. Και τα σφάλματα του υπολογιστή σταμάτησαν από μόνα τους όταν το επίπεδο ακτινοβολίας μειώθηκε με την πάροδο του χρόνου.

Μέσα από τους σωλήνες

Μια φορά κι έναν καιρό, η Movietech Solutions δημιούργησε λογισμικό για κινηματογράφους, σχεδιασμένο για λογιστικά, πωλήσεις εισιτηρίων και γενική διαχείριση. Η έκδοση DOS της ναυαρχίδας εφαρμογής ήταν αρκετά δημοφιλής μεταξύ των μικρών και μεσαίων αλυσίδων κινηματογραφικών αιθουσών στη Βόρεια Αμερική. Επομένως, δεν αποτελεί έκπληξη το γεγονός ότι όταν ανακοινώθηκε μια έκδοση των Windows 95, ενσωματωμένη με τις πιο πρόσφατες οθόνες αφής και περίπτερα αυτοεξυπηρέτησης και εξοπλισμένη με όλα τα είδη εργαλείων αναφοράς, έγινε επίσης δημοφιλής. Τις περισσότερες φορές η ενημέρωση έγινε χωρίς προβλήματα. Το τοπικό προσωπικό πληροφορικής εγκατέστησε νέο εξοπλισμό, μετέφερε δεδομένα και η επιχείρηση συνεχίστηκε. Εκτός από όταν δεν κράτησε. Όταν συνέβαινε αυτό, η εταιρεία θα έστελνε τον James, με το παρατσούκλι "The Cleaner".

Αν και το παρατσούκλι υποδηλώνει έναν κακόβουλο τύπο, το καθαριστικό είναι απλώς ένας συνδυασμός εκπαιδευτή, εγκαταστάτη και jack-of-all-trades. Ο Τζέιμς περνούσε μερικές μέρες στον ιστότοπο του πελάτη συναρμολογώντας όλα τα εξαρτήματα και, στη συνέχεια, περνούσε άλλες δύο μέρες διδάσκοντας στο προσωπικό πώς να χρησιμοποιήσει το νέο σύστημα, λύνοντας τυχόν προβλήματα υλικού που προέκυπταν και βοηθώντας ουσιαστικά το λογισμικό στην αρχή του.

Επομένως, δεν αποτελεί έκπληξη το γεγονός ότι σε αυτές τις έντονες στιγμές, ο Τζέιμς έφτασε στο γραφείο το πρωί και πριν προλάβει να φτάσει στο γραφείο του, τον υποδέχτηκε ο διευθυντής, γεμάτος καφεΐνη πέρα ​​από το συνηθισμένο.

«Φοβάμαι ότι πρέπει να πάτε στην Αννάπολη της Νέας Σκωτίας το συντομότερο δυνατό». Ολόκληρο το σύστημά τους κατέρρευσε και μετά από μια νύχτα εργασίας με τους μηχανικούς τους, δεν μπορούμε να καταλάβουμε τι συνέβη. Φαίνεται ότι το δίκτυο απέτυχε στον διακομιστή. Αλλά μόνο αφού το σύστημα είχε λειτουργήσει για αρκετά λεπτά.

— Δεν επέστρεψαν στο παλιό σύστημα; - απάντησε εντελώς σοβαρά ο Τζέιμς, αν και νοερά άνοιξε τα μάτια του από έκπληξη.

— Ακριβώς: ο ειδικός πληροφορικής τους «άλλαξε προτεραιότητες» και αποφάσισε να φύγει με τον παλιό τους διακομιστή. James, εγκατέστησαν το σύστημα σε έξι τοποθεσίες και μόλις πλήρωσαν για premium υποστήριξη, και η επιχείρησή τους λειτουργεί τώρα όπως ήταν τη δεκαετία του 1950.

Ο Τζέιμς ίσιωσε ελαφρά.

- Αυτό είναι άλλο θέμα. Εντάξει, ας ξεκινήσουμε.

Όταν έφτασε στην Αννάπολη, το πρώτο πράγμα που έκανε ήταν να βρει το πρώτο θέατρο του πελάτη που είχε πρόβλημα. Στον χάρτη που τραβήχτηκε στο αεροδρόμιο, όλα φαίνονταν αξιοπρεπή, αλλά η περιοχή γύρω από την επιθυμητή διεύθυνση φαινόταν ύποπτη. Όχι γκέτο, αλλά θυμίζει φιλμ νουάρ. Καθώς ο Τζέιμς στάθμευε στο πεζοδρόμιο στο κέντρο της πόλης, μια πόρνη τον πλησίασε. Δεδομένου του μεγέθους της Αννάπολης, πιθανότατα ήταν η μοναδική σε ολόκληρη την πόλη. Η εμφάνισή της έφερε αμέσως στο μυαλό τον διάσημο χαρακτήρα που πρόσφερε σεξ για χρήματα στη μεγάλη οθόνη. Όχι, όχι για την Τζούλια Ρόμπερτς, αλλά για τον Τζον Βόιτ [νύξη στην ταινία "Midnight Cowboy" - περίπου. λωρίδα].

Έχοντας στείλει την πόρνη στο δρόμο της, ο Τζέιμς πήγε στον κινηματογράφο. Η γύρω περιοχή είχε βελτιωθεί, αλλά παρόλα αυτά έδινε την εντύπωση ότι έχει καταρρεύσει. Όχι ότι ο Τζέιμς ανησυχούσε πολύ. Έχει ξαναπάει σε άθλια μέρη. Και αυτός ήταν ο Καναδάς, όπου ακόμη και οι ληστές είναι αρκετά ευγενικοί για να πουν «ευχαριστώ» αφού πάρουν το πορτοφόλι σου.

Η πλαϊνή είσοδος του κινηματογράφου ήταν σε ένα κατάφυτο δρομάκι. Ο Τζέιμς προχώρησε προς την πόρτα και χτύπησε. Σύντομα έτριξε και άνοιξε ελαφρά.

-Είσαι καθαρίστρια; - ακούστηκε μια βραχνή φωνή από μέσα.

- Ναι, είμαι εγώ... Ήρθα να τα φτιάξω όλα.

Ο Τζέιμς μπήκε στο λόμπι του κινηματογράφου. Προφανώς δεν έχοντας άλλη επιλογή, το προσωπικό άρχισε να μοιράζει χάρτινα εισιτήρια στους επισκέπτες. Αυτό δυσκόλεψε την οικονομική αναφορά, πόσο μάλλον πιο ενδιαφέρουσες λεπτομέρειες. Αλλά το προσωπικό υποδέχτηκε τον Τζέιμς με ανακούφιση και τον πήγε αμέσως στο δωμάτιο του διακομιστή.

Με την πρώτη ματιά, όλα ήταν καλά. Ο Τζέιμς συνδέθηκε στον διακομιστή και έλεγξε τα συνηθισμένα ύποπτα μέρη. Κανένα πρόβλημα. Ωστόσο, από πολλή προσοχή, ο James έκλεισε τον διακομιστή, αντικατέστησε την κάρτα δικτύου και επανέφερε το σύστημα. Αμέσως άρχισε να δουλεύει πλήρως. Το προσωπικό άρχισε πάλι να πουλάει εισιτήρια.

Ο Τζέιμς τηλεφώνησε στον Μαρκ και τον ενημέρωσε για την κατάσταση. Δεν είναι δύσκολο να φανταστεί κανείς ότι ο Τζέιμς μπορεί να θέλει να μείνει και να δει αν συμβεί κάτι απροσδόκητο. Κατέβηκε τις σκάλες και άρχισε να ρωτά τους υπαλλήλους τι συνέβη. Προφανώς το σύστημα έχει σταματήσει να λειτουργεί. Το έκλεισαν και το άναψαν, όλα λειτουργούσαν. Αλλά μετά από 10 λεπτά το σύστημα έπεσε.

Απλώς αυτή τη στιγμή συνέβη κάτι παρόμοιο. Ξαφνικά, το σύστημα έκδοσης εισιτηρίων άρχισε να ρίχνει λάθη. Το προσωπικό αναστέναξε και άρπαξε τα χάρτινα εισιτήρια και ο Τζέιμς πήγε βιαστικά στο δωμάτιο του διακομιστή. Όλα φαίνονταν καλά με τον διακομιστή.

Τότε μπήκε ένας από τους υπαλλήλους.

— Το σύστημα λειτουργεί ξανά.

Ο Τζέιμς σάστισε γιατί δεν είχε κάνει τίποτα. Πιο συγκεκριμένα, τίποτα που θα έκανε το σύστημα να λειτουργήσει. Αποχώρησε, σήκωσε το τηλέφωνό του και κάλεσε τη γραμμή υποστήριξης της εταιρείας του. Σύντομα ο ίδιος υπάλληλος μπήκε στο δωμάτιο του διακομιστή.

- Το σύστημα είναι εκτός λειτουργίας.

Ο Τζέιμς έριξε μια ματιά στον διακομιστή. Ένα ενδιαφέρον και οικείο μοτίβο πολύχρωμων σχημάτων χόρευε στην οθόνη - στριφογυρίζοντας χαοτικά και μπλέκοντας σωλήνες. Όλοι έχουμε δει αυτήν την προφύλαξη οθόνης κάποια στιγμή. Αποδόθηκε όμορφα και κυριολεκτικά υπνωτιστικό.


Ο Τζέιμς πάτησε ένα κουμπί και το σχέδιο εξαφανίστηκε. Έσπευσε στο εκδοτήριο εισιτηρίων και στο δρόμο συνάντησε έναν υπάλληλο που επέστρεφε κοντά του.

— Το σύστημα λειτουργεί ξανά.

Αν μπορείς να κάνεις μια διανοητική παλάμη, αυτό ακριβώς έκανε ο Τζέιμς. Προφύλαξη οθόνης. Χρησιμοποιεί OpenGL. Και επομένως, κατά τη λειτουργία, καταναλώνει όλους τους πόρους του επεξεργαστή διακομιστή. Ως αποτέλεσμα, κάθε κλήση προς τον διακομιστή τελειώνει με χρονικό όριο.

Ο Τζέιμς επέστρεψε στο δωμάτιο του διακομιστή, συνδέθηκε και αντικατέστησε την προφύλαξη οθόνης με τους όμορφους αγωγούς με μια κενή οθόνη. Δηλαδή, αντί για μια προφύλαξη οθόνης που καταναλώνει το 100% των πόρων του επεξεργαστή, εγκατέστησα μια άλλη που δεν καταναλώνει πόρους. Μετά περίμενα 10 λεπτά για να ελέγξω την εικασία μου.

Όταν ο Τζέιμς έφτασε στον επόμενο κινηματογράφο, αναρωτιόταν πώς να εξηγήσει στον μάνατζέρ του ότι μόλις είχε πετάξει 800 χιλιόμετρα για να απενεργοποιήσει την προφύλαξη οθόνης.

Συντριβή κατά τη διάρκεια μιας ορισμένης φάσης του φεγγαριού

Αληθινή ιστορία. Μια μέρα εμφανίστηκε ένα σφάλμα λογισμικού που εξαρτιόταν από τη φάση της σελήνης. Υπήρχε μια μικρή ρουτίνα που χρησιμοποιήθηκε συνήθως σε διάφορα προγράμματα του MIT για τον υπολογισμό της προσέγγισης στην πραγματική φάση της Σελήνης. Η GLS ενσωμάτωσε αυτή τη ρουτίνα σε ένα πρόγραμμα LISP το οποίο, όταν έγραφε ένα αρχείο, θα έβγαζε μια γραμμή με χρονική σήμανση μήκους σχεδόν 80 χαρακτήρων. Ήταν πολύ σπάνιο ότι η πρώτη γραμμή ενός μηνύματος κατέληγε να είναι πολύ μεγάλη και να οδηγούσε στην επόμενη γραμμή. Και όταν αργότερα το πρόγραμμα διάβασε αυτό το αρχείο, καταράστηκε. Το μήκος της πρώτης γραμμής εξαρτιόταν από την ακριβή ημερομηνία και ώρα, καθώς και από το μήκος της προδιαγραφής φάσης τη στιγμή που τυπώθηκε η χρονική σήμανση. Δηλαδή το bug κυριολεκτικά εξαρτιόταν από τη φάση του φεγγαριού!

Πρώτη έντυπη έκδοση Αρχείο Jargon (Steele-1983) περιείχε ένα παράδειγμα μιας τέτοιας γραμμής που οδήγησε στο περιγραφόμενο σφάλμα, αλλά ο στοιχειοθέτης το "διόρθωσε". Αυτό έχει περιγραφεί από τότε ως "σφάλμα της φάσης της σελήνης".

Ωστόσο, να είστε προσεκτικοί με τις υποθέσεις. Πριν από μερικά χρόνια, μηχανικοί από το CERN (Ευρωπαϊκό Κέντρο Πυρηνικής Έρευνας) αντιμετώπισαν σφάλματα σε πειράματα που πραγματοποιήθηκαν στον Μεγάλο Επιταχυντή Ηλεκτρονίων-Ποζιτρονίων. Δεδομένου ότι οι υπολογιστές επεξεργάζονται ενεργά τον τεράστιο όγκο δεδομένων που δημιουργείται από αυτήν τη συσκευή πριν δείξουν το αποτέλεσμα στους επιστήμονες, πολλοί υπέθεσαν ότι το λογισμικό ήταν κατά κάποιο τρόπο ευαίσθητο στη φάση του φεγγαριού. Αρκετοί απελπισμένοι μηχανικοί έφτασαν στο βάθος της αλήθειας. Το σφάλμα προέκυψε λόγω μιας μικρής αλλαγής στη γεωμετρία του μήκους 27 χιλιομέτρων δακτυλίου λόγω της παραμόρφωσης της Γης κατά το πέρασμα της Σελήνης! Αυτή η ιστορία έχει μπει στη λαογραφία της φυσικής ως «Η εκδίκηση του Νεύτωνα για τη Φυσική των Σωματιδίων» και ένα παράδειγμα της σύνδεσης μεταξύ των απλούστερων και παλαιότερων νόμων της φυσικής και των πιο προηγμένων επιστημονικών εννοιών.

Το ξέπλυμα της τουαλέτας σταματά το τρένο

Το καλύτερο σφάλμα υλικού που έχω ακούσει ποτέ ήταν σε ένα τρένο υψηλής ταχύτητας στη Γαλλία. Το σφάλμα οδήγησε σε έκτακτο φρενάρισμα της αμαξοστοιχίας, αλλά μόνο εάν επέβαιναν επιβάτες. Σε κάθε τέτοια περίπτωση, το τρένο έβγαινε εκτός λειτουργίας, ελέγχθηκε, αλλά δεν βρέθηκε τίποτα. Στη συνέχεια τον έστειλαν πίσω στη γραμμή και αμέσως έπεσε και σταμάτησε.

Κατά τη διάρκεια ενός από τους ελέγχους, ένας μηχανικός που ταξίδευε στο τρένο πήγε στην τουαλέτα. Σε λίγο ξεβράστηκε, ΜΠΟΥΜ! Στάση έκτακτης ανάγκης.

Ο μηχανικός επικοινώνησε με τον οδηγό και ρώτησε:

— Τι κάνατε λίγο πριν φρενάρετε;

- Λοιπόν, έκοψα ταχύτητα στην κατάβαση...

Αυτό ήταν περίεργο, γιατί κατά τη διάρκεια της κανονικής λειτουργίας το τρένο επιβραδύνει στις κατηφόρες δεκάδες φορές. Το τρένο προχώρησε και στην επόμενη κάθοδο ο οδηγός προειδοποίησε:

- Πάω να επιβραδύνω.

Δεν έγινε τίποτα.

— Τι έκανες στο τελευταίο φρενάρισμα; - ρώτησε ο οδηγός.

- Λοιπόν, ήμουν στην τουαλέτα...

- Λοιπόν, πήγαινε στην τουαλέτα και κάνε ό,τι έκανες όταν ξαναπάμε κάτω!

Ο μηχανικός πήγε στην τουαλέτα και όταν ο οδηγός προειδοποίησε: «Κραδεύω ταχύτητα», ξεπλύθηκε το νερό. Φυσικά το τρένο σταμάτησε αμέσως.

Τώρα μπορούσαν να αναπαράγουν το πρόβλημα και έπρεπε να βρουν την αιτία.

Μετά από δύο λεπτά, παρατήρησαν ότι το καλώδιο του τηλεχειριστηρίου του φρένου κινητήρα (το τρένο είχε έναν κινητήρα σε κάθε άκρο) ήταν αποσυνδεδεμένο από το τοίχωμα του ηλεκτρικού θαλάμου και βρισκόταν στο ρελέ που έλεγχε την ηλεκτρομαγνητική βαλβίδα της τουαλέτας... Όταν το ρελέ ήταν ενεργοποιημένο, δημιούργησε παρεμβολές στο καλώδιο του φρένου και η προστασία του συστήματος από βλάβες περιλάμβανε απλώς φρενάρισμα έκτακτης ανάγκης.

Η πύλη που μισούσε το FORTRAN

Πριν από λίγους μήνες παρατηρήσαμε ότι οι συνδέσεις δικτύου στην ηπειρωτική χώρα [αυτό ήταν στη Χαβάη] γίνονταν πολύ, πολύ αργές. Αυτό μπορεί να διαρκέσει για 10-15 λεπτά και στη συνέχεια να συμβεί ξανά ξαφνικά. Μετά από λίγο, ο συνάδελφός μου μου παραπονέθηκε ότι οι συνδέσεις δικτύου στην ηπειρωτική χώρα γενικά δεν δουλεύει. Είχε κάποιο κωδικό FORTRAN που έπρεπε να αντιγραφεί σε ένα μηχάνημα στην ηπειρωτική χώρα, αλλά δεν μπορούσε επειδή "το δίκτυο δεν άντεξε αρκετά για να ολοκληρωθεί η μεταφόρτωση FTP".

Ναι, αποδείχθηκε ότι παρουσιάστηκαν αποτυχίες δικτύου όταν ένας συνάδελφος προσπάθησε να μεταφέρει ένα αρχείο με πηγαίο κώδικα στο FORTRAN σε ένα μηχάνημα στην ηπειρωτική χώρα. Προσπαθήσαμε να αρχειοθετήσουμε το αρχείο: στη συνέχεια αντιγράφηκε ομαλά (αλλά το μηχάνημα προορισμού δεν είχε αποσυσκευασία, επομένως το πρόβλημα δεν λύθηκε). Τελικά «χωρίσαμε» τον κωδικό FORTRAN σε πολύ μικρά κομμάτια και τα στέλναμε ένα-ένα. Τα περισσότερα από τα κομμάτια αντιγράφηκαν χωρίς προβλήματα, αλλά μερικά κομμάτια δεν πέρασαν ή πέρασαν μετά πολυάριθμος προσπάθειες.

Όταν εξετάσαμε τα προβληματικά αποσπάσματα, ανακαλύψαμε ότι είχαν κάτι κοινό: όλα περιείχαν μπλοκ σχολίων που ξεκινούσαν και τελείωναν με γραμμές που αποτελούνταν από κεφαλαίο C (όπως ένας συνάδελφος προτιμούσε να σχολιάσει στο FORTRAN). Στείλαμε email σε ειδικούς του δικτύου στην ηπειρωτική χώρα και ζητήσαμε βοήθεια. Φυσικά ήθελαν να δουν δείγματα των αρχείων μας που δεν μπορούσαν να μεταφερθούν μέσω FTP... αλλά τα γράμματά μας δεν τους έφτασαν. Τελικά καταλήξαμε σε ένα απλό περιγράφωπώς μοιάζουν τα μη μεταβιβάσιμα αρχεία. Λειτουργούσε :) [Να τολμήσω να προσθέσω ένα παράδειγμα ενός από τα προβληματικά σχόλια του FORTRAN εδώ; Μάλλον δεν αξίζει τον κόπο!]

Στο τέλος καταφέραμε να το καταλάβουμε. Μια νέα πύλη εγκαταστάθηκε πρόσφατα μεταξύ του τμήματος της πανεπιστημιούπολης μας και του ηπειρωτικού δικτύου. Είχε ΤΕΡΑΣΤΙΑ δυσκολία στη μετάδοση πακέτων που περιείχαν επαναλαμβανόμενα bits κεφαλαίων C! Μόνο μερικά από αυτά τα πακέτα θα μπορούσαν να καταλάβουν όλους τους πόρους της πύλης και να αποτρέψουν τη διέλευση των περισσότερων άλλων πακέτων. Διαμαρτυρηθήκαμε στον κατασκευαστή της πύλης... και απάντησαν: «Ω, ναι, αντιμετωπίζετε ένα σφάλμα επαναλαμβανόμενου C! Γνωρίζουμε ήδη γι' αυτόν». Τελικά λύσαμε το πρόβλημα αγοράζοντας μια νέα πύλη από άλλο κατασκευαστή (προς υπεράσπιση του πρώτου, η αδυναμία μεταφοράς προγραμμάτων FORTRAN μπορεί να είναι πλεονέκτημα για ορισμένους!).

Τις δυσκολες στιγμες

Πριν από μερικά χρόνια, ενώ εργαζόμουν για τη δημιουργία ενός συστήματος ETL στο Perl για τη μείωση του κόστους των κλινικών δοκιμών φάσης 40, χρειάστηκε να επεξεργαστώ περίπου 000 ημερομηνίες. Δύο από αυτούς δεν πέρασαν το τεστ. Αυτό δεν με ενόχλησε πολύ, επειδή αυτές οι ημερομηνίες ελήφθησαν από δεδομένα που παρείχε ο πελάτης που συχνά, ας πούμε, ήταν εκπληκτικά. Αλλά όταν έλεγξα τα αρχικά δεδομένα, αποδείχθηκε ότι αυτές οι ημερομηνίες ήταν η 1η Ιανουαρίου 2011 και η 1η Ιανουαρίου 2007. Νόμιζα ότι το σφάλμα περιείχε το πρόγραμμα που μόλις είχα γράψει, αλλά αποδείχθηκε ότι ήταν ήδη 30 χρόνια παλαιός. Αυτό μπορεί να ακούγεται μυστηριώδες σε όσους δεν είναι εξοικειωμένοι με το οικοσύστημα λογισμικού. Λόγω της μακροχρόνιας απόφασης μιας άλλης εταιρείας να βγάλει χρήματα, ο πελάτης μου με πλήρωσε για να διορθώσω ένα σφάλμα που η μια εταιρεία παρουσίασε κατά λάθος και η άλλη επίτηδες. Για να καταλάβετε για τι πράγμα μιλάω, πρέπει να μιλήσω για την εταιρεία που πρόσθεσε το χαρακτηριστικό που κατέληξε να γίνει σφάλμα, καθώς και μερικά άλλα ενδιαφέροντα γεγονότα που συνέβαλαν στο μυστηριώδες σφάλμα που διόρθωσα.

Τις παλιές καλές μέρες, οι υπολογιστές της Apple μερικές φορές επαναέφεραν αυθόρμητα την ημερομηνία τους στην 1η Ιανουαρίου 1904. Ο λόγος ήταν απλός: χρησιμοποιούσε ένα «ρολόι συστήματος» που τροφοδοτείται από μπαταρία για να παρακολουθεί την ημερομηνία και την ώρα. Τι συνέβη όταν πέθανε η μπαταρία; Οι υπολογιστές άρχισαν να παρακολουθούν την ημερομηνία με τον αριθμό των δευτερολέπτων από την αρχή μιας εποχής. Με τον όρο εποχή εννοούσαμε την αρχική ημερομηνία αναφοράς, και για τα Macintosh ήταν η 1η Ιανουαρίου 1904. Και μετά το τέλος της μπαταρίας, η τρέχουσα ημερομηνία επαναφέρθηκε στην καθορισμένη. Γιατί όμως συνέβη αυτό;

Προηγουμένως, η Apple χρησιμοποιούσε 32 bit για να αποθηκεύσει τον αριθμό των δευτερολέπτων από την αρχική ημερομηνία. Ένα bit μπορεί να αποθηκεύσει μία από τις δύο τιμές - 1 ή 0. Δύο bit μπορούν να αποθηκεύσουν μία από τις τέσσερις τιμές: 00, 01, 10, 11. Τρία bit - μία τιμή από οκτώ: 000, 001, 010, 011, 100 , 101, 110, 111, κ.λπ. Και το 32 θα μπορούσε να αποθηκεύσει μία από τις 232 τιμές, δηλαδή 4 δευτερόλεπτα. Για τις ημερομηνίες της Apple, αυτό ισοδυναμούσε με περίπου 294 χρόνια, επομένως οι παλαιότεροι Mac δεν μπορούν να χειριστούν ημερομηνίες μετά το 967. Και αν η μπαταρία του συστήματος εξαντληθεί, η ημερομηνία επαναφέρεται στα 296 δευτερόλεπτα από την αρχή της εποχής και πρέπει να ορίζετε χειροκίνητα την ημερομηνία κάθε φορά που ανοίγετε τον υπολογιστή (ή μέχρι να αγοράσετε μια νέα μπαταρία).

Ωστόσο, η απόφαση της Apple να αποθηκεύσει τις ημερομηνίες ως δευτερόλεπτα από την εποχή σήμαινε ότι δεν μπορούσαμε να επεξεργαστούμε ημερομηνίες πριν από την εποχή, κάτι που είχε εκτεταμένες συνέπειες, όπως θα δούμε. Η Apple παρουσίασε ένα χαρακτηριστικό, όχι ένα σφάλμα. Μεταξύ άλλων, αυτό σήμαινε ότι το λειτουργικό σύστημα Macintosh είχε ανοσία στο «σφάλμα της χιλιετίας» (κάτι που δεν μπορούσε να ειπωθεί για πολλές εφαρμογές Mac που είχαν τα δικά τους συστήματα ημερομηνίας για να παρακάμψουν τους περιορισμούς).

Προχώρα. Χρησιμοποιήσαμε το Lotus 1-2-3, τη «δολοφονική εφαρμογή» της IBM που βοήθησε να ξεκινήσει η επανάσταση των υπολογιστών, αν και οι υπολογιστές της Apple είχαν VisiCalc, το οποίο έκανε τον προσωπικό υπολογιστή επιτυχημένο. Για να είμαστε δίκαιοι, αν δεν είχε εμφανιστεί το 1-2-3, οι υπολογιστές δύσκολα θα είχαν απογειωθεί και η ιστορία των προσωπικών υπολογιστών θα μπορούσε να είχε εξελιχθεί πολύ διαφορετικά. Το Lotus 1-2-3 αντιμετώπισε εσφαλμένα το 1900 ως δίσεκτο έτος. Όταν η Microsoft κυκλοφόρησε το πρώτο της υπολογιστικό φύλλο, το Multiplan, κατέλαβε ένα μικρό μερίδιο της αγοράς. Και όταν ξεκίνησαν το έργο Excel, αποφάσισαν όχι μόνο να αντιγράψουν το σχήμα ονοματοδοσίας σειρών και στηλών από το Lotus 1-2-3, αλλά και να εξασφαλίσουν συμβατότητα με σφάλματα αντιμετωπίζοντας σκόπιμα το 1900 ως δίσεκτο έτος. Αυτό το πρόβλημα υπάρχει ακόμα και σήμερα. Έτσι, στο 1-2-3 ήταν ένα σφάλμα, αλλά στο Excel ήταν μια συνειδητή απόφαση να διασφαλιστεί ότι και οι 1-2-3 χρήστες θα μπορούσαν να εισάγουν τους πίνακές τους στο Excel χωρίς να αλλάξουν τα δεδομένα, ακόμα κι αν ήταν λάθος.

Υπήρχε όμως ένα άλλο πρόβλημα. Πρώτον, η Microsoft κυκλοφόρησε το Excel για Macintosh, το οποίο δεν αναγνώριζε ημερομηνίες πριν από την 1η Ιανουαρίου 1904. Και στο Excel, η 1η Ιανουαρίου 1900 θεωρήθηκε η αρχή της εποχής. Ως εκ τούτου, οι προγραμματιστές έκαναν μια αλλαγή έτσι ώστε το πρόγραμμά τους να αναγνωρίζει τον τύπο της εποχής και να αποθηκεύει δεδομένα μέσα του σύμφωνα με την επιθυμητή εποχή. Η Microsoft έγραψε ακόμη και ένα επεξηγηματικό άρθρο σχετικά με αυτό. Και αυτή η απόφαση οδήγησε στο σφάλμα μου.

Το σύστημά μου ETL έλαβε υπολογιστικά φύλλα Excel από πελάτες που δημιουργήθηκαν σε Windows, αλλά μπορούσαν επίσης να δημιουργηθούν σε Mac. Επομένως, η αρχή της εποχής στον πίνακα θα μπορούσε να είναι είτε η 1η Ιανουαρίου 1900 είτε η 1η Ιανουαρίου 1904. Πώς να μάθετε; Η μορφή αρχείου Excel εμφανίζει τις απαραίτητες πληροφορίες, αλλά ο αναλυτής που χρησιμοποίησα δεν τις εμφανίζει (τώρα το εμφανίζει) και υπέθεσε ότι γνωρίζετε την εποχή για έναν συγκεκριμένο πίνακα. Πιθανότατα θα μπορούσα να είχα ξοδέψει περισσότερο χρόνο για να κατανοήσω τη δυαδική μορφή του Excel και να στείλω μια ενημέρωση κώδικα στον συντάκτη του αναλυτή, αλλά είχα πολλά περισσότερα να κάνω για τον πελάτη, οπότε έγραψα γρήγορα μια ευρετική για να προσδιορίσω την εποχή. Ήταν απλή.

Στο Excel, η ημερομηνία 5 Ιουλίου 1998 μπορεί να αναπαρασταθεί με τη μορφή "07-05-98" (άχρηστο αμερικανικό σύστημα), "5 Ιουλίου 98", "5 Ιουλίου 1998", "5-Ιουλ-98" ή κάποια άλλη μορφή, μια άλλη άχρηστη μορφή (ειρωνικά, μια από τις μορφές που δεν πρόσφερε η έκδοση του Excel μου ήταν το ISO 8601). Ωστόσο, στον πίνακα, η μη μορφοποιημένη ημερομηνία αποθηκεύτηκε είτε ως "35981" για την εποχή-1900 ή "34519" για την εποχή-1904 (οι αριθμοί αντιπροσωπεύουν τον αριθμό των ημερών από την εποχή). Απλώς χρησιμοποίησα έναν απλό αναλυτή για να εξαγάγω το έτος από τη μορφοποιημένη ημερομηνία και, στη συνέχεια, χρησιμοποίησα τον αναλυτή Excel για να εξαγάγω το έτος από την ημερομηνία χωρίς μορφοποίηση. Εάν και οι δύο τιμές διέφεραν κατά 4 χρόνια, τότε ήξερα ότι χρησιμοποιούσα ένα σύστημα με το epoch-1904.

Γιατί δεν χρησιμοποίησα απλώς μορφοποιημένες ημερομηνίες; Επειδή η 5 Ιουλίου 1998 μπορεί να μορφοποιηθεί ως "Ιούλιος, 98" με την ημέρα του μήνα χαμένη. Λάβαμε πίνακες από τόσες πολλές εταιρείες που τους δημιούργησαν με τόσους διαφορετικούς τρόπους που εναπόκειτο σε εμάς (στην προκειμένη περίπτωση, σε εμένα) να καταλάβουμε τις ημερομηνίες. Άλλωστε, αν το Excel τα καταφέρνει σωστά, τότε πρέπει να το κάνουμε κι εμείς!

Ταυτόχρονα συνάντησα το 39082. Να θυμίσω ότι το Lotus 1-2-3 θεωρούσε το 1900 δίσεκτο έτος, και αυτό επαναλήφθηκε πιστά στο Excel. Και δεδομένου ότι αυτό προστέθηκε μία ημέρα στο έτος 1900, πολλές συναρτήσεις υπολογισμού ημερομηνίας μπορεί να είναι λανθασμένες για εκείνη ακριβώς την ημέρα. Δηλαδή, το 39082 θα μπορούσε να ήταν 1 Ιανουαρίου 2011 (σε Mac) ή 31 Δεκεμβρίου 2006 (στα Windows). Εάν ο "αναλυτής έτους" μου εξήγαγε το έτος 2011 από τη μορφοποιημένη τιμή, τότε όλα είναι καλά. Αλλά επειδή ο αναλυτής του Excel δεν γνωρίζει ποια εποχή χρησιμοποιείται, ορίζει ως προεπιλογή το epoch-1900, επιστρέφοντας το έτος 2006. Η αίτησή μου είδε ότι η διαφορά ήταν 5 χρόνια, το θεώρησε σφάλμα, το κατέγραψε και επέστρεψε μια μη μορφοποιημένη τιμή.

Για να το ξεπεράσω αυτό, έγραψα αυτό (ψευδοκώδικας):

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

Και τότε και οι 40 ημερομηνίες αναλύθηκαν σωστά.

Στη μέση των μεγάλων εργασιών εκτύπωσης

Στις αρχές της δεκαετίας του 1980, ο πατέρας μου εργαζόταν στο Storage Technology, ένα τμήμα που δεν λειτουργεί πλέον και δημιουργούσε μηχανισμούς κίνησης ταινίας και πνευματικά συστήματα για τροφοδοσία ταινίας υψηλής ταχύτητας.

Επανασχεδίασαν τους δίσκους έτσι ώστε να μπορούν να έχουν μια κεντρική μονάδα δίσκου "A" συνδεδεμένη σε επτά μονάδες "B" και το μικρό λειτουργικό σύστημα στη μνήμη RAM που έλεγχε τη μονάδα "A" θα μπορούσε να αναθέτει λειτουργίες ανάγνωσης και εγγραφής σε όλες τις μονάδες "B".

Κάθε φορά που ξεκινούσε η μονάδα δίσκου "A", ήταν απαραίτητο να εισάγετε μια δισκέτα στην περιφερειακή μονάδα που ήταν συνδεδεμένη στο "A" για να φορτωθεί το λειτουργικό σύστημα στη μνήμη του. Ήταν εξαιρετικά πρωτόγονο: η υπολογιστική ισχύς παρεχόταν από έναν μικροελεγκτή 8 bit.

Το κοινό-στόχος για τέτοιο εξοπλισμό ήταν εταιρείες με πολύ μεγάλες αποθήκες δεδομένων -τράπεζες, αλυσίδες λιανικής κ.λπ.- που έπρεπε να εκτυπώσουν πολλές ετικέτες διευθύνσεων ή αντίγραφα τραπεζικών κινήσεων.

Ένας πελάτης είχε πρόβλημα. Στη μέση μιας εργασίας εκτύπωσης, μια συγκεκριμένη μονάδα δίσκου "A" θα μπορούσε να σταματήσει να λειτουργεί, με αποτέλεσμα να σταματήσει ολόκληρη η εργασία. Για να αποκατασταθεί η λειτουργία της μονάδας δίσκου, το προσωπικό έπρεπε να επανεκκινήσει τα πάντα. Και αν αυτό συνέβαινε στη μέση μιας εξάωρης εργασίας, τότε χάθηκε ένας τεράστιος ακριβός χρόνος υπολογιστή και το χρονοδιάγραμμα ολόκληρης της επιχείρησης διαταράχθηκε.

Στάλθηκαν τεχνικοί από την Storage Technologies. Όμως, παρά τις καλύτερες προσπάθειές τους, δεν μπόρεσαν να αναπαραγάγουν το σφάλμα υπό συνθήκες δοκιμής: φαινόταν να εμφανίζεται στη μέση των μεγάλων εργασιών εκτύπωσης. Το πρόβλημα δεν ήταν το υλικό, αντικατέστησαν ό,τι μπορούσαν: RAM, μικροελεγκτή, μονάδα δισκέτας, κάθε πιθανό μέρος της μονάδας ταινίας - το πρόβλημα παρέμεινε.

Τότε οι τεχνικοί κάλεσαν το αρχηγείο και κάλεσαν τον Εμπειρογνώμονα.

Ο ειδικός άρπαξε μια καρέκλα και ένα φλιτζάνι καφέ, κάθισε στην αίθουσα υπολογιστών -εκείνες τις μέρες υπήρχαν δωμάτια αφιερωμένα στους υπολογιστές- και παρακολουθούσε καθώς το προσωπικό έβαζε στην ουρά μια μεγάλη εργασία εκτύπωσης. Ο ειδικός περίμενε να συμβεί μια αποτυχία - και έγινε. Όλοι κοίταξαν τον Εμπειρογνώμονα, αλλά δεν είχε ιδέα γιατί συνέβη αυτό. Έτσι, διέταξε να μπει ξανά η δουλειά στην ουρά και όλο το προσωπικό και οι τεχνικοί επέστρεψαν στη δουλειά.

Ο ειδικός κάθισε ξανά στην καρέκλα και άρχισε να περιμένει μια αποτυχία. Πέρασαν περίπου έξι ώρες και σημειώθηκε η αποτυχία. Ο ειδικός πάλι δεν είχε ιδέα, εκτός από το ότι όλα συνέβησαν σε ένα δωμάτιο γεμάτο κόσμο. Διέταξε να ξαναρχίσει η αποστολή, κάθισε πίσω και περίμενε.

Με την τρίτη αποτυχία, ο ειδικός παρατήρησε κάτι. Η αποτυχία σημειώθηκε όταν το προσωπικό άλλαξε ταινίες σε μια ξένη μονάδα δίσκου. Επιπλέον, η αποτυχία σημειώθηκε μόλις ένας από τους υπαλλήλους πέρασε μέσα από ένα συγκεκριμένο πλακάκι στο πάτωμα.

Το υπερυψωμένο δάπεδο ήταν κατασκευασμένο από πλακάκια αλουμινίου τοποθετημένα σε ύψος 6 έως 8 ίντσες. Πολλά καλώδια από υπολογιστές περνούσαν κάτω από το υπερυψωμένο πάτωμα για να αποτρέψουν κάποιον από το να πατήσει κατά λάθος ένα σημαντικό καλώδιο. Τα πλακάκια τοποθετήθηκαν πολύ σφιχτά για να αποφευχθεί η είσοδος υπολειμμάτων κάτω από το υπερυψωμένο δάπεδο.

Ο ειδικός συνειδητοποίησε ότι ένα από τα πλακάκια ήταν παραμορφωμένο. Όταν ένας υπάλληλος πάτησε στη γωνία του, οι άκρες του πλακιδίου τρίβονταν στα διπλανά πλακάκια. Τα πλαστικά μέρη που συνέδεαν τα πλακάκια επίσης τρίβονταν με αυτά, γεγονός που προκάλεσε στατικές μικροεκφορτίσεις που δημιουργούσαν παρεμβολές ραδιοσυχνοτήτων.

Σήμερα, η μνήμη RAM προστατεύεται πολύ καλύτερα από παρεμβολές ραδιοσυχνοτήτων. Όμως εκείνα τα χρόνια δεν ίσχυε αυτό. Ο ειδικός συνειδητοποίησε ότι αυτή η παρεμβολή διέκοψε τη μνήμη, και μαζί με αυτήν τη λειτουργία του λειτουργικού συστήματος. Κάλεσε την υπηρεσία υποστήριξης, παρήγγειλε νέα πλακάκια, τα τοποθέτησε μόνος του και το πρόβλημα εξαφανίστηκε.

Είναι παλίρροια!

Η ιστορία διαδραματίστηκε σε ένα δωμάτιο διακομιστή, στον τέταρτο ή πέμπτο όροφο ενός γραφείου στο Πόρτσμουθ (νομίζω), στην περιοχή των αποβάθρων.

Μια μέρα ο διακομιστής Unix με την κύρια βάση δεδομένων κατέρρευσε. Τον επανεκκίνησαν, αλλά συνέχισε ευτυχώς να πέφτει ξανά και ξανά. Αποφασίσαμε να καλέσουμε κάποιον από την υπηρεσία υποστήριξης.

Ο τύπος υποστήριξης... Νομίζω ότι λεγόταν Μαρκ, αλλά αυτό δεν έχει σημασία... Δεν νομίζω ότι τον ξέρω. Δεν πειράζει, πραγματικά. Ας μείνουμε με τον Μαρκ, εντάξει; Εξαιρετική.

Έτσι, λίγες ώρες αργότερα ο Mark έφτασε (δεν είναι πολύ μακριά από το Leeds στο Portsmouth, ξέρετε), άνοιξε τον διακομιστή και όλα λειτουργούσαν χωρίς προβλήματα. Τυπική καταραμένη υποστήριξη, ο πελάτης αναστατώνεται πολύ γι' αυτό. Ο Mark ψάχνει μέσα από τα αρχεία καταγραφής και δεν βρίσκει τίποτα ενοχλητικό. Έτσι ο Mark επιστρέφει στο τρένο (ή με όποιο τρόπο μεταφοράς έφτασε, θα μπορούσε να ήταν μια κουτσή αγελάδα για ό,τι ξέρω... τέλος πάντων, δεν πειράζει, εντάξει;) και κατευθύνεται πίσω στο Λιντς, έχοντας σπαταλήσει η μέρα.

Το ίδιο βράδυ ο διακομιστής κολλάει ξανά. Η ιστορία είναι η ίδια... ο διακομιστής δεν σηκώνεται. Ο Mark προσπαθεί να βοηθήσει απομακρυσμένα, αλλά ο πελάτης δεν μπορεί να ξεκινήσει τον διακομιστή.

Άλλο ένα τρένο, λεωφορείο, μαρέγκα λεμονιού ή κάποια άλλη χάλια, και ο Μαρκ επέστρεψε στο Πόρτσμουθ. Κοιτάξτε, ο διακομιστής εκκινεί χωρίς κανένα πρόβλημα! Θαύμα. Ο Μαρκ αφιερώνει αρκετές ώρες ελέγχοντας ότι όλα είναι εντάξει με το λειτουργικό σύστημα ή το λογισμικό και ξεκινά για το Λιντς.

Γύρω στα μέσα της ημέρας ο διακομιστής κολλάει (ήρε!). Αυτή τη φορά φαίνεται λογικό να φέρουμε άτομα υποστήριξης υλικού για να αντικαταστήσουν τον διακομιστή. Όχι όμως, μετά από 10 ώρες περίπου πέφτει.

Η κατάσταση επαναλήφθηκε για αρκετές μέρες. Ο διακομιστής λειτουργεί, κολλάει μετά από περίπου 10 ώρες και δεν ξεκινά για τις επόμενες 2 ώρες. Έλεγξαν ψύξη, διαρροές μνήμης, έλεγξαν τα πάντα, αλλά δεν βρήκαν τίποτα. Μετά σταμάτησαν οι συντριβές.

Η εβδομάδα πέρασε ξέγνοιαστα... όλοι χάρηκαν. Ευτυχισμένος μέχρι να ξαναρχίσουν όλα. Η εικόνα είναι η ίδια. 10 ώρες δουλειά, 2-3 ώρες διακοπές...

Και τότε κάποιος (νομίζω ότι μου είπαν ότι αυτό το άτομο δεν είχε καμία σχέση με το IT) είπε:

"Είναι η παλίρροια!"

Το επιφώνημα αντιμετωπίστηκε με κενά βλέμματα και το χέρι κάποιου μάλλον δίστασε στο κουμπί κλήσης ασφαλείας.

«Σταματά να λειτουργεί με την παλίρροια».

Αυτό φαίνεται να είναι μια εντελώς ξένη ιδέα για τους εργαζόμενους στην υποστήριξη IT, οι οποίοι είναι απίθανο να διαβάσουν την Επετηρίδα Tide ενώ κάθονται για καφέ. Εξήγησαν ότι αυτό δεν θα μπορούσε να σχετίζεται με την παλίρροια με κανέναν τρόπο, επειδή ο διακομιστής δούλευε για μια εβδομάδα χωρίς αποτυχίες.

«Την περασμένη εβδομάδα η παλίρροια ήταν χαμηλή, αλλά αυτή την εβδομάδα είναι υψηλή».

Λίγη ορολογία για όσους δεν έχουν άδεια σκάφους. Οι παλίρροιες εξαρτώνται από τον σεληνιακό κύκλο. Και καθώς η Γη περιστρέφεται, κάθε 12,5 ώρες η βαρυτική έλξη του Ήλιου και της Σελήνης δημιουργεί ένα παλιρροϊκό κύμα. Στην αρχή του κύκλου των 12,5 ωρών υπάρχει υψηλή παλίρροια, στη μέση του κύκλου υπάρχει άμπωτη και στο τέλος υπάρχει πάλι υψηλή παλίρροια. Αλλά καθώς αλλάζει η τροχιά του φεγγαριού, αλλάζει και η διαφορά μεταξύ χαμηλής και υψηλής παλίρροιας. Όταν η Σελήνη βρίσκεται μεταξύ του Ήλιου και της Γης ή στην αντίθετη πλευρά της Γης (πανσέληνος ή καθόλου φεγγάρι), έχουμε παλίρροιες Syzygyn - τις υψηλότερες υψηλές παλίρροιες και τις χαμηλότερες χαμηλές παλίρροιες. Στο μισό φεγγάρι έχουμε τετράγωνες παλίρροιες - τις χαμηλότερες παλίρροιες. Η διαφορά μεταξύ των δύο άκρων μειώνεται πολύ. Ο σεληνιακός κύκλος διαρκεί 28 ημέρες: συζυγικός - τετράγωνος - συζυγικός - τετραγωνισμός.

Όταν οι τεχνικοί εξήγησαν την ουσία των παλιρροϊκών δυνάμεων, σκέφτηκαν αμέσως ότι έπρεπε να καλέσουν την αστυνομία. Και αρκετά λογικό. Αλλά αποδεικνύεται ότι ο μάγκας είχε δίκιο. Δύο εβδομάδες νωρίτερα, ένα αντιτορπιλικό έδεσε κοντά στο γραφείο. Κάθε φορά που η παλίρροια το ανέβαζε σε ένα ορισμένο ύψος, η θέση ραντάρ του πλοίου κατέληγε στο επίπεδο του δαπέδου του δωματίου διακομιστή. Και το ραντάρ (ή εξοπλισμός ηλεκτρονικού πολέμου, ή κάποιο άλλο στρατιωτικό παιχνίδι) δημιούργησε χάος στους υπολογιστές.

Αποστολή πτήσης για τον πύραυλο

Μου ανατέθηκε να μεταφέρω ένα μεγάλο (περίπου 400 χιλιάδες γραμμές) σύστημα ελέγχου και παρακολούθησης εκτόξευσης πυραύλων σε νέες εκδόσεις του λειτουργικού συστήματος, του μεταγλωττιστή και της γλώσσας. Πιο συγκεκριμένα, από το Solaris 2.5.1 έως το Solaris 7, και από το Verdix Ada Development System (VADS), γραμμένο στο Ada 83, στο σύστημα Rational Apex Ada, γραμμένο στο Ada 95. Το VADS αγοράστηκε από τη Rational και το προϊόν της ήταν παρωχημένο, αν και η Rational προσπάθησε να εφαρμόσει συμβατές εκδόσεις πακέτων ειδικά για VADS για να διευκολύνει τη μετάβαση στον μεταγλωττιστή Apex.

Τρία άτομα με βοήθησαν να μεταγλωττίσω τον κώδικα καθαρά. Χρειάστηκαν δύο εβδομάδες. Και μετά δούλεψα μόνος μου για να λειτουργήσει το σύστημα. Με λίγα λόγια, ήταν η χειρότερη αρχιτεκτονική και υλοποίηση συστήματος λογισμικού που είχα συναντήσει, οπότε χρειάστηκαν άλλοι δύο μήνες για να ολοκληρωθεί η θύρα. Στη συνέχεια, το σύστημα υποβλήθηκε για δοκιμή, η οποία διήρκεσε αρκετούς μήνες ακόμη. Διόρθωσα αμέσως τα σφάλματα που βρέθηκαν κατά τη διάρκεια της δοκιμής, αλλά ο αριθμός τους μειώθηκε γρήγορα (ο πηγαίος κώδικας ήταν ένα σύστημα παραγωγής, επομένως η λειτουργικότητά του λειτούργησε αρκετά αξιόπιστα, απλά έπρεπε να αφαιρέσω τα σφάλματα που προέκυψαν κατά την προσαρμογή στον νέο μεταγλωττιστή). Τελικά, όταν όλα λειτουργούσαν όπως έπρεπε, μεταφέρθηκα σε άλλο έργο.

Και την Παρασκευή πριν από την Ημέρα των Ευχαριστιών, χτύπησε το τηλέφωνο.

Η εκτόξευση πυραύλων υποτίθεται ότι θα δοκιμαστεί σε περίπου τρεις εβδομάδες και κατά τη διάρκεια εργαστηριακών δοκιμών της αντίστροφης μέτρησης, η σειρά των εντολών μπλοκαρίστηκε. Στην πραγματική ζωή, αυτό θα ματαίωνε τη δοκιμή και εάν το μπλοκάρισμα εμφανιζόταν μέσα σε λίγα δευτερόλεπτα από την εκκίνηση του κινητήρα, θα συνέβαιναν αρκετές μη αναστρέψιμες ενέργειες στα βοηθητικά συστήματα, κάτι που θα απαιτούσε μακρά -και ακριβή- ετοιμότητα του πυραύλου. Δεν θα είχε ξεκινήσει, αλλά πολλοί άνθρωποι θα είχαν στεναχωρηθεί πολύ για την απώλεια χρόνου και πολλά, πολλά χρήματα. Μην αφήσετε κανέναν να σας πει ότι το Υπουργείο Άμυνας ξοδεύει χρήματα απερίσκεπτα - δεν έχω συναντήσει ποτέ συμβασιούχο διευθυντή που να μην έβαλε τον προϋπολογισμό πρώτο ή δεύτερο, ακολουθούμενο από χρονοδιάγραμμα.

Τους προηγούμενους μήνες, αυτή η πρόκληση αντίστροφης μέτρησης είχε εκτελεστεί εκατοντάδες φορές σε πολλές παραλλαγές, με μόνο μερικά μικρά προβλήματα. Έτσι, η πιθανότητα να συμβεί αυτό ήταν πολύ μικρή, αλλά οι συνέπειές του ήταν πολύ σημαντικές. Πολλαπλασιάστε και τους δύο αυτούς παράγοντες και θα καταλάβετε ότι οι ειδήσεις προέβλεπαν μια κατεστραμμένη εβδομάδα διακοπών για εμένα και δεκάδες μηχανικούς και διευθυντές.

Και δόθηκε προσοχή σε εμένα ως το άτομο που μετέφερε το σύστημα.

Όπως συμβαίνει με τα περισσότερα κρίσιμα για την ασφάλεια συστήματα, καταγράφηκαν πολλές παράμετροι, επομένως ήταν αρκετά εύκολο να εντοπιστούν οι λίγες γραμμές κώδικα που εκτελέστηκαν πριν από τη συντριβή του συστήματος. Και φυσικά, δεν υπήρχε απολύτως τίποτα ασυνήθιστο σε αυτά· οι ίδιες εκφράσεις είχαν εκτελεστεί με επιτυχία κυριολεκτικά χιλιάδες φορές κατά τη διάρκεια της ίδιας διαδρομής.

Καλέσαμε τους ανθρώπους από το Apex στο Rational επειδή ήταν αυτοί που ανέπτυξαν τον μεταγλωττιστή και ορισμένες από τις ρουτίνες που ανέπτυξαν καλούνταν στον ύποπτο κώδικα. Αυτοί (και όλοι οι άλλοι) εντυπωσιάστηκαν ότι υπήρχε ανάγκη να μπουν στη ρίζα ενός προβλήματος κυριολεκτικά εθνικής σημασίας.

Επειδή δεν υπήρχε τίποτα ενδιαφέρον στα περιοδικά, αποφασίσαμε να προσπαθήσουμε να αναπαράγουμε το πρόβλημα σε ένα τοπικό εργαστήριο. Αυτό δεν ήταν εύκολο έργο, καθώς το συμβάν λάμβανε χώρα περίπου μία φορά ανά 1000 τρεξίματα. Ένας ύποπτος λόγος ήταν ότι μια κλήση σε μια συνάρτηση mutex που αναπτύχθηκε από τον προμηθευτή (μέρος του πακέτου μετεγκατάστασης VADS) Unlock δεν οδήγησε σε ξεκλείδωμα. Το νήμα επεξεργασίας που καλούσε τη συνάρτηση επεξεργαζόταν μηνύματα καρδιακού παλμού, τα οποία έφταναν ονομαστικά κάθε δευτερόλεπτο. Ανεβάσαμε τη συχνότητα στα 10 Hz, δηλαδή 10 φορές το δευτερόλεπτο, και αρχίσαμε να τρέχουμε. Περίπου μια ώρα αργότερα το σύστημα κλειδώθηκε. Στο αρχείο καταγραφής, είδαμε ότι η ακολουθία των ηχογραφημένων μηνυμάτων ήταν η ίδια όπως κατά την αποτυχημένη δοκιμή. Κάναμε πολλές ακόμη διαδρομές, το σύστημα ήταν σταθερά μπλοκαρισμένο 45-90 λεπτά μετά την εκκίνηση και κάθε φορά το αρχείο καταγραφής περιείχε την ίδια διαδρομή. Παρόλο που εκτελούσαμε τεχνικά διαφορετικό κώδικα - η συχνότητα του μηνύματος ήταν διαφορετική - η συμπεριφορά του συστήματος ήταν η ίδια, επομένως ήμασταν σίγουροι ότι αυτό το σενάριο φόρτωσης προκαλούσε το ίδιο πρόβλημα.

Τώρα έπρεπε να καταλάβουμε πού ακριβώς συνέβη το μπλοκάρισμα στην ακολουθία των εκφράσεων.

Αυτή η υλοποίηση του συστήματος χρησιμοποιούσε το σύστημα εργασιών Ada και το χρησιμοποίησε απίστευτα κακώς. Οι εργασίες είναι μια υψηλού επιπέδου ταυτόχρονα εκτελέσιμη κατασκευή στο Ada, κάτι σαν νήματα εκτέλεσης, ενσωματωμένα μόνο στην ίδια τη γλώσσα. Όταν δύο εργασίες πρέπει να επικοινωνήσουν, «ορίζουν ένα ραντεβού», ανταλλάσσουν τα απαραίτητα δεδομένα και μετά σταματούν το ραντεβού και επιστρέφουν στις ανεξάρτητες εκτελέσεις τους. Ωστόσο, το σύστημα εφαρμόστηκε διαφορετικά. Μετά το ραντεβού μιας εργασίας στόχου, αυτή η εργασία στόχος συναντήθηκε με μια άλλη εργασία, η οποία στη συνέχεια συναντήθηκε με μια τρίτη εργασία και ούτω καθεξής μέχρι να ολοκληρωθεί κάποια επεξεργασία. Μετά από αυτό, όλα αυτά τα ραντεβού ολοκληρώθηκαν και κάθε εργασία έπρεπε να επιστρέψει στην εκτέλεσή της. Δηλαδή, είχαμε να κάνουμε με το πιο ακριβό σύστημα κλήσης συναρτήσεων στον κόσμο, το οποίο σταμάτησε ολόκληρη τη διαδικασία «πολλαπλών εργασιών» ενώ επεξεργαζόταν μέρος των δεδομένων εισόδου. Και πριν αυτό δεν οδήγησε σε προβλήματα μόνο επειδή η απόδοση ήταν πολύ χαμηλή.

Περιέγραψα αυτόν τον μηχανισμό εργασιών επειδή όταν ζητήθηκε ή αναμενόταν να ολοκληρωθεί ένα ραντεβού, θα μπορούσε να προκύψει ένας "εναλλαγή εργασιών". Δηλαδή, ο επεξεργαστής θα μπορούσε να ξεκινήσει την επεξεργασία μιας άλλης εργασίας που είναι έτοιμη να εκτελεστεί. Αποδεικνύεται ότι όταν μια εργασία είναι έτοιμη για ραντεβού με μια άλλη εργασία, μια εντελώς διαφορετική εργασία μπορεί να αρχίσει να εκτελείται και τελικά ο έλεγχος επιστρέφει στο πρώτο ραντεβού. Και άλλα συμβάντα μπορεί να προκύψουν που προκαλούν εναλλαγή της εργασίας. Ένα τέτοιο συμβάν είναι μια κλήση σε μια λειτουργία συστήματος, όπως η εκτύπωση ή η εκτέλεση μιας mutex.

Για να καταλάβω ποια γραμμή κώδικα προκαλούσε το πρόβλημα, χρειάστηκε να βρω έναν τρόπο να καταγράψω την πρόοδο μέσω μιας ακολουθίας δηλώσεων χωρίς να ενεργοποιήσω έναν διακόπτη εργασιών, ο οποίος θα απέτρεπε την εμφάνιση σφαλμάτων. Οπότε δεν μπορούσα να εκμεταλλευτώ Put_Line()για να αποφύγετε την εκτέλεση λειτουργιών I/O. Θα μπορούσα να ορίσω μια μεταβλητή μετρητή ή κάτι παρόμοιο, αλλά πώς μπορώ να δω την τιμή της εάν δεν μπορώ να την εμφανίσω στην οθόνη;

Επίσης, κατά την εξέταση του αρχείου καταγραφής, προέκυψε ότι, παρά την επεξεργασία των μηνυμάτων καρδιακού παλμού, η οποία εμπόδιζε όλες τις λειτουργίες I/O της διεργασίας και εμπόδιζε την εκτέλεση άλλης επεξεργασίας, συνέχισαν να εκτελούνται άλλες ανεξάρτητες εργασίες. Δηλαδή, το έργο δεν μπλοκαρίστηκε εντελώς, μόνο μια (κρίσιμη) αλυσίδα εργασιών.

Αυτή ήταν η ένδειξη που χρειαζόταν για την αξιολόγηση της έκφρασης αποκλεισμού.

Έφτιαξα ένα πακέτο Ada που περιείχε μια εργασία, έναν απαριθμημένο τύπο και μια καθολική μεταβλητή αυτού του τύπου. Αριθμητικά κυριολεκτικά δεσμεύτηκαν σε συγκεκριμένες εκφράσεις της προβληματικής ακολουθίας (π.χ. Incrementing_Buffer_Index, Locking_Mutex, Mutex_Unlocked), και στη συνέχεια εισήγαγε εκφράσεις ανάθεσης σε αυτό που εκχωρούσαν την αντίστοιχη απαρίθμηση σε μια καθολική μεταβλητή. Δεδομένου ότι ο κωδικός αντικειμένου όλων αυτών απλώς αποθήκευε μια σταθερά στη μνήμη, η εναλλαγή εργασιών ως αποτέλεσμα της εκτέλεσής της ήταν εξαιρετικά απίθανη. Κυρίως ήμασταν ύποπτοι για εκφράσεις που θα μπορούσαν να αλλάξουν την εργασία, καθώς ο αποκλεισμός συνέβη κατά την εκτέλεση αντί να επιστρέψει κατά την αλλαγή της εργασίας (για διάφορους λόγους).

Η εργασία παρακολούθησης απλώς έτρεχε σε έναν βρόχο και ελέγχονταν περιοδικά για να δούμε αν η τιμή της καθολικής μεταβλητής είχε αλλάξει. Με κάθε αλλαγή, η τιμή αποθηκεύτηκε σε ένα αρχείο. Στη συνέχεια, μια σύντομη αναμονή και ένας νέος έλεγχος. Έγραψα τη μεταβλητή στο αρχείο επειδή η εργασία εκτελέστηκε μόνο όταν το σύστημα την επέλεξε για εκτέλεση κατά την εναλλαγή της εργασίας στην προβληματική περιοχή. Ό,τι και να συνέβαινε σε αυτήν την εργασία δεν θα επηρεάσει άλλες, άσχετες μπλοκαρισμένες εργασίες.

Αναμενόταν ότι όταν το σύστημα φτάσει στο σημείο εκτέλεσης του προβληματικού κώδικα, η καθολική μεταβλητή θα επαναφερόταν κατά τη μετάβαση σε κάθε επόμενη έκφραση. Τότε θα συμβεί κάτι που θα προκαλέσει την εναλλαγή της εργασίας και δεδομένου ότι η συχνότητα εκτέλεσής της (10 Hz) είναι χαμηλότερη από αυτή της εργασίας παρακολούθησης, η οθόνη θα μπορούσε να καταγράψει την τιμή της καθολικής μεταβλητής και να τη γράψει. Σε μια κανονική κατάσταση, θα μπορούσα να λάβω μια επαναλαμβανόμενη ακολουθία ενός υποσυνόλου απαρίθμησης: τις τελευταίες τιμές της μεταβλητής τη στιγμή της αλλαγής εργασιών. Κατά την ανάρτηση, η καθολική μεταβλητή δεν θα πρέπει πλέον να αλλάζει και η τελευταία τιμή που γράφτηκε θα υποδεικνύει ποια έκφραση δεν ολοκληρώθηκε.

Έτρεξα τον κωδικό με παρακολούθηση. Πάγωσε. Και η παρακολούθηση λειτουργούσε σαν ρολόι.

Το αρχείο καταγραφής περιείχε την αναμενόμενη ακολουθία, η οποία διακόπηκε από μια τιμή που υποδεικνύει ότι είχε κληθεί ένα mutex Unlock, και η εργασία δεν ολοκληρώθηκε - όπως συμβαίνει με χιλιάδες προηγούμενες κλήσεις.

Οι μηχανικοί της Apex ανέλυαν πυρετωδώς τον κώδικά τους αυτή τη στιγμή και βρήκαν μια θέση στο mutex όπου, θεωρητικά, θα μπορούσε να συμβεί ένα κλείδωμα. Αλλά η πιθανότητά του ήταν πολύ χαμηλή, καθώς μόνο μια συγκεκριμένη ακολουθία γεγονότων που συνέβαιναν σε μια συγκεκριμένη στιγμή θα μπορούσε να οδηγήσει σε αποκλεισμό. Ο νόμος του Μέρφι, παιδιά, είναι ο νόμος του Μέρφι.

Για να προστατεύσω το κομμάτι του κώδικα που χρειαζόμουν, αντικατέστησα τις κλήσεις συνάρτησης mutex (χτισμένες πάνω από τη λειτουργικότητα mutex του λειτουργικού συστήματος) με ένα μικρό εγγενές πακέτο Ada mutex για τον έλεγχο της πρόσβασης mutex σε αυτό το κομμάτι.

Το έβαλα στον κώδικα και έτρεξα το τεστ. Επτά ώρες αργότερα ο κωδικός εξακολουθούσε να λειτουργεί.

Ο κώδικάς μου υποβλήθηκε στο Rational, όπου τον μεταγλώτισαν, τον αποσυναρμολόγησαν και έλεγξαν ότι δεν χρησιμοποιούσε την ίδια προσέγγιση που χρησιμοποιήθηκε στις προβληματικές συναρτήσεις mutex.

Αυτή ήταν η πιο πολυσύχναστη ανασκόπηση κώδικα της καριέρας μου 🙂 Υπήρχαν περίπου δέκα μηχανικοί και διευθυντές στο δωμάτιο μαζί μου, άλλα δέκα άτομα ήταν σε μια κλήση συνδιάσκεψης - και όλοι εξέτασαν περίπου 20 γραμμές κώδικα.

Ο κώδικας αναθεωρήθηκε, νέα εκτελέσιμα αρχεία συγκεντρώθηκαν και υποβλήθηκαν για επίσημη δοκιμή παλινδρόμησης. Μερικές εβδομάδες αργότερα, η δοκιμή αντίστροφης μέτρησης ήταν επιτυχής και ο πύραυλος απογειώθηκε.

Εντάξει, καλά όλα αυτά, αλλά ποιο είναι το νόημα της ιστορίας;

Ήταν ένα απολύτως αηδιαστικό πρόβλημα. Εκατοντάδες χιλιάδες γραμμές κώδικα, παράλληλη εκτέλεση, πάνω από δώδεκα διαδικασίες αλληλεπίδρασης, κακή αρχιτεκτονική και κακή υλοποίηση, διεπαφές για ενσωματωμένα συστήματα και ξοδεύτηκαν εκατομμύρια δολάρια. Καμία πίεση, σωστά.

Δεν ήμουν ο μόνος που δούλευα πάνω σε αυτό το πρόβλημα, αν και ήμουν στο επίκεντρο καθώς έκανα τη μεταφορά. Αλλά παρόλο που το έκανα, αυτό δεν σημαίνει ότι κατάλαβα όλες τις εκατοντάδες χιλιάδες γραμμές κώδικα, ή ακόμα και τις κοίταξα. Ο κώδικας και τα αρχεία καταγραφής αναλύθηκαν από μηχανικούς σε όλη τη χώρα, αλλά όταν μου είπαν τις υποθέσεις τους για τα αίτια της αποτυχίας, μου πήρε μόνο μισό λεπτό για να τις διαψεύσω. Και όταν μου ζητούσαν να αναλύσω θεωρίες, το διέδιδα σε κάποιον άλλο, γιατί ήταν προφανές για μένα ότι αυτοί οι μηχανικοί πήγαιναν σε λάθος δρόμο. Ακούγεται αλαζονικό; Ναι, αυτό είναι αλήθεια, αλλά απέρριψα τις υποθέσεις και τα αιτήματα για έναν άλλο λόγο.

Κατάλαβα τη φύση του προβλήματος. Δεν ήξερα ακριβώς πού συνέβαινε ή γιατί, αλλά ήξερα τι συνέβαινε.

Με τα χρόνια, έχω συσσωρεύσει πολλές γνώσεις και εμπειρία. Ήμουν ένας από τους πρωτοπόρους στη χρήση του Ada και κατάλαβα τα πλεονεκτήματα και τα μειονεκτήματά του. Γνωρίζω πώς οι βιβλιοθήκες χρόνου εκτέλεσης Ada χειρίζονται εργασίες και αντιμετωπίζουν την παράλληλη εκτέλεση. Και καταλαβαίνω προγραμματισμό χαμηλού επιπέδου σε επίπεδο μνήμης, καταχωρητών και συναρμολογητή. Με άλλα λόγια, έχω βαθιά γνώση στον τομέα μου. Και τα χρησιμοποίησα για να βρω την αιτία του προβλήματος. Δεν επιλύσα απλώς το σφάλμα, κατάλαβα πώς να το βρω σε ένα πολύ ευαίσθητο περιβάλλον χρόνου εκτέλεσης.

Τέτοιες ιστορίες πάλης με κώδικα δεν είναι πολύ ενδιαφέρουσες για όσους δεν είναι εξοικειωμένοι με τα χαρακτηριστικά και τις συνθήκες ενός τέτοιου αγώνα. Αλλά αυτές οι ιστορίες μας βοηθούν να καταλάβουμε τι χρειάζεται για να λύσουμε πραγματικά δύσκολα προβλήματα.

Για να λύσετε πραγματικά δύσκολα προβλήματα, πρέπει να είστε κάτι περισσότερο από προγραμματιστής. Πρέπει να κατανοήσετε τη «μοίρα» του κώδικα, πώς αλληλεπιδρά με το περιβάλλον του και πώς λειτουργεί το ίδιο το περιβάλλον.

Και τότε θα έχετε τη δική σας κατεστραμμένη εβδομάδα διακοπών.

Συνεχίζεται.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο