Folklore om programmører og ingeniører (del 1)

Folklore om programmører og ingeniører (del 1)

Dette er et udvalg af historier fra internettet om, hvordan fejl nogle gange har helt utrolige manifestationer. Måske har du også noget at fortælle.

Bilallergi over for vaniljeis

En historie for ingeniører, der forstår, at det åbenlyse ikke altid er svaret, og at uanset hvor langt ude fakta kan virke, så er de stadig fakta. Pontiac Division af General Motors Corporation modtog en klage:

Det er anden gang, jeg skriver til dig, og jeg bebrejder dig ikke for ikke at svare, for det lyder skørt. Vores familie har tradition for at spise is hver aften efter aftensmaden. Istyperne skifter hver gang, og efter aftensmaden vælger hele familien, hvilken is der skal købes, hvorefter jeg går i butikken. Jeg har for nylig købt en ny Pontiac, og siden da er mine ture for at få is blevet et problem. Ser du, hver gang jeg køber vaniljeis og kommer tilbage fra butikken, vil bilen ikke starte. Hvis jeg medbringer anden is, starter bilen uden problemer. Jeg vil stille et seriøst spørgsmål, uanset hvor dumt det lyder: "Hvad er det ved Pontiac'en, der gør, at den ikke starter, når jeg tager vaniljeis med, men starter let, når jeg tager en anden smag af is?"

Som du kan forestille dig, var divisionsformanden skeptisk over for brevet. Men for en sikkerheds skyld sendte jeg en ingeniør for at tjekke det. Han var overrasket over, at han blev mødt af en velhavende, veluddannet mand, der bor i et smukt område. De aftalte at mødes umiddelbart efter aftensmaden, så de to kunne gå i butikken efter is. Den aften var det vanilje, og da de kom tilbage til bilen, ville den ikke starte.

Ingeniøren kom tre aftener mere. Første gang var isen chokolade. Bilen startede. Anden gang var der jordbæris. Bilen startede. Den tredje aften bad han om at tage vanilje. Bilen startede ikke.

Fornuftsmæssigt ræsonnerede ingeniøren nægtede at tro, at bilen var allergisk over for vaniljeis. Derfor aftalte jeg med ejeren af ​​bilen, at han ville fortsætte sine besøg, indtil han fandt en løsning på problemet. Og undervejs begyndte han at tage noter: han skrev alle oplysninger ned, tidspunkt på dagen, type benzin, ankomsttidspunkt og retur fra butikken osv.

Ingeniøren indså hurtigt, at ejeren af ​​bilen brugte mindre tid på at købe vaniljeis. Årsagen var indretningen af ​​varerne i butikken. Vaniljeis var den mest populære og blev opbevaret i en separat fryser forrest i butikken for at gøre det nemmere at finde. Og alle de andre varianter lå bagerst i butikken, og det tog meget længere tid at finde den rigtige sort og betale.

Nu var spørgsmålet til ingeniøren: hvorfor startede bilen ikke, hvis der var gået mindre tid siden det øjeblik, motoren blev slukket? Da problemet var tiden, ikke vaniljeis, fandt ingeniøren hurtigt svaret: det var en gaslås. Det skete hver aften, men da bilejeren brugte mere tid på at lede efter is, nåede motoren at køle nok af og startede let. Og da manden købte vaniljeis, var motoren stadig for varm, og gaslåsen nåede ikke at gå i opløsning.

Moral: Selv helt skøre problemer er nogle gange virkelige.

Crash Bandicoot

Det er smertefuldt at opleve dette. Som programmør vænner du dig til at give din kode skylden først, anden, tredje... og et eller andet sted på ti tusindepladsen giver du compileren skylden. Og længere nede på listen giver du allerede udstyret skylden.

Her er min historie om hardwarefejlen.

Til spillet Crash Bandicoot skrev jeg kode til at indlæse og gemme på et hukommelseskort. For sådan en selvglad spiludvikler var det som en tur i parken: Jeg troede, at arbejdet ville tage flere dage. Jeg endte dog med at fejlsøge koden i seks uger. Undervejs løste jeg andre problemer, men med få dages mellemrum vendte jeg tilbage til denne kode i et par timer. Det var smerte.

Symptomet så således ud: Når du gemmer spillets aktuelle gennemspilning og får adgang til hukommelseskortet, går alt næsten altid fint... Men nogle gange ophører læse- eller skriveoperationen uden åbenbar grund. En kort optagelse beskadiger ofte hukommelseskortet. Når en spiller forsøger at redde, undlader han ikke kun at redde, men ødelægger også kortet. Crap.

Efter et stykke tid begyndte vores producer hos Sony, Connie Bus, at gå i panik. Vi kunne ikke sende spillet med denne fejl, og seks uger senere forstod jeg ikke, hvad der forårsagede problemet. Gennem Connie kontaktede vi andre PS1-udviklere: er der nogen, der er stødt på noget lignende? Ingen. Ingen havde problemer med hukommelseskortet.

Når du ikke har nogen ideer til fejlretning, er den eneste tilgang tilbage at "dele og herske": Fjern mere og mere kode fra det defekte program, indtil der er et relativt lille fragment tilbage, der stadig forårsager problemet. Det vil sige, at du afskærer programmet stykke for stykke, indtil den del, der indeholder fejlen, bliver tilbage.

Men sagen er, at det er meget svært at skære bidder ud af et videospil. Hvordan kører man det, hvis man fjernede koden, der emulerer tyngdekraften? Eller tegne karakterer?

Derfor er vi nødt til at erstatte hele moduler med stubbe, der foregiver at gøre noget nyttigt, men i virkeligheden gør noget meget simpelt, som ikke kan indeholde fejl. Vi er nødt til at skrive sådanne krykker, for at spillet i det mindste virker. Dette er en langsom og smertefuld proces.

Kort sagt, jeg gjorde det. Jeg fjernede flere og flere stykker kode, indtil jeg stod tilbage med den indledende kode, der konfigurerer systemet til at køre spillet, initialiserer gengivelseshardwaren osv. Selvfølgelig kunne jeg på dette tidspunkt ikke oprette en gem og indlæs menu, fordi jeg skulle oprette en stub for al grafikkoden. Men jeg kunne foregive at være en bruger ved at bruge den (usynlige) gemme- og indlæsningsskærm og bede om at gemme og derefter skrive til hukommelseskortet.

Dette efterlod mig med et lille stykke kode, der stadig havde ovenstående problem - men det skete stadig tilfældigt! Oftest fungerede alt fint, men indimellem var der fejl. Jeg fjernede næsten al spilkoden, men fejlen var stadig i live. Dette var gådefuldt: den resterende kode gjorde faktisk ikke noget.

På et tidspunkt, formentlig omkring tre om morgenen, faldt en tanke op for mig. Læse- og skriveoperationer (input/output) involverer præcise udførelsestider. Når du arbejder med en harddisk, et hukommelseskort eller et Bluetooth-modul, gør lavniveaukoden, der er ansvarlig for læsning og skrivning, det i overensstemmelse med urimpulser.

Ved hjælp af et ur synkroniseres en enhed, der ikke er direkte forbundet med processoren, med den kode, der udføres på processoren. Uret bestemmer baudhastigheden - den hastighed, hvormed data transmitteres. Hvis der er forvirring med timings, så er enten hardwaren eller softwaren eller begge dele også forvirrede. Og det er meget dårligt, fordi dataene kan blive beskadiget.

Hvad hvis noget i vores kode forvirrer timingen? Jeg tjekkede alt relateret til dette i testprogramkoden og bemærkede, at vi indstillede den programmerbare timer i PS1 til 1 kHz (1000 tikker i sekundet). Dette er ret meget; som standard, når konsollen starter, kører den ved 100 Hz. Og de fleste spil bruger denne frekvens.

Andy, spiludvikleren, indstillede timeren til 1 kHz, så bevægelser ville blive beregnet mere præcist. Andy har en tendens til at gå overbord, og hvis vi efterligner tyngdekraften, gør vi det så præcist som muligt!

Men hvad nu, hvis en fremskyndelse af timeren på en eller anden måde påvirkede programmets overordnede timing og dermed uret, der regulerer baudhastigheden for hukommelseskortet?

Jeg kommenterede timerkoden. Fejlen opstod ikke igen. Men det betyder ikke, at vi har rettet det, for fejlen opstod tilfældigt. Hvad hvis jeg bare var heldig?

Et par dage senere eksperimenterede jeg igen med testprogrammet. Fejlen gentog sig ikke. Jeg gik tilbage til den fulde spilkodebase og ændrede gem- og indlæsningskoden, så den programmerbare timer ville nulstille til sin oprindelige værdi (100Hz), før jeg fik adgang til hukommelseskortet, og derefter nulstilles til 1kHz. Der var ikke flere styrt.

Men hvorfor skete dette?

Jeg vendte tilbage til testprogrammet igen. Jeg forsøgte at finde et eller andet mønster i forekomsten af ​​en fejl med en 1 kHz timer. Til sidst bemærkede jeg, at fejlen opstår, når nogen spiller med en PS1-controller. Da jeg sjældent ville gøre dette selv - hvorfor skulle jeg bruge en controller, når jeg tester gem og indlæs kode? - Jeg bemærkede ikke engang denne afhængighed. Men en dag ventede en af ​​vores kunstnere på, at jeg var færdig med at teste - jeg bandede nok i det øjeblik - og drejede nervøst controlleren i hænderne. Der opstod en fejl. "Vent, hvad?!" Nå, gør det igen!"

Da jeg indså, at disse to begivenheder var forbundet, var jeg i stand til nemt at genskabe fejlen: Jeg begyndte at optage til hukommelseskortet, flyttede controlleren og ødelagde hukommelseskortet. For mig lignede det en hardwarefejl.

Jeg kom til Connie og fortalte hende om min opdagelse. Hun videresendte oplysningerne til en af ​​ingeniørerne, der designede PS1. "Umuligt," svarede han, "det kan ikke være et hardwareproblem." Jeg bad Connie om at arrangere en samtale for os.

Ingeniøren ringede til mig, og vi skændtes på hans gebrokken engelsk og mit (ekstremt) gebrokede japansk. Til sidst sagde jeg: "Lad mig bare sende mit 30 linjers testprogram, hvor flytning af controlleren forårsager en fejl." Han var enig. Sagde, at det var spild af tid, og at han havde frygtelig travlt med at arbejde på et nyt projekt, men ville give efter, fordi vi var en meget vigtig udvikler for Sony. Jeg ryddede op i mit testprogram og sendte det til ham.

Næste aften (vi var i Los Angeles, og han var i Tokyo) ringede han til mig og undskyldte fåragtigt. Det var et hardwareproblem.

Jeg ved ikke præcis, hvad fejlen var, men ud fra hvad jeg hørte i Sonys hovedkvarter, hvis du indstillede timeren til en høj nok værdi, forstyrrede den komponenter på bundkortet i nærheden af ​​timerkrystallen. En af dem var en baudrate-controller til hukommelseskortet, som også indstillede baudraten for controllerne. Jeg er ikke ingeniør, så jeg har måske rodet noget ud.

Men den nederste linje er, at der var interferens mellem komponenter på bundkortet. Og når der transmitteres data samtidigt gennem controllerporten og hukommelseskortporten med en timer, der kører på 1 kHz, gik bits tabt, data gik tabt, og kortet blev beskadiget.

Dårlige køer

I 1980'erne skrev min mentor Sergei software til SM-1800, en sovjetisk klon af PDP-11. Denne mikrocomputer er netop blevet installeret på en jernbanestation nær Sverdlovsk, et vigtigt transportknudepunkt i USSR. Det nye system blev designet til at dirigere vogne og godstrafik. Men den indeholdt en irriterende fejl, der førte til tilfældige nedbrud og nedbrud. Fald opstod altid, når nogen gik hjem om aftenen. Men trods en grundig undersøgelse dagen efter fungerede computeren korrekt i alle manuelle og automatiske test. Dette indikerer normalt en race tilstand eller en anden konkurrencefejl, der opstår under visse forhold. Træt af opkald sent om aftenen besluttede Sergei at komme til bunds i det og først og fremmest forstå, hvilke forhold på rangerpladsen førte til computernedbrud.

Først indsamlede han statistik over alle uforklarlige fald og lavede en graf efter dato og klokkeslæt. Mønstret var tydeligt. Efter at have observeret et par dage mere indså Sergei, at han nemt kunne forudsige tidspunktet for fremtidige systemfejl.

Han erfarede hurtigt, at forstyrrelser kun opstod, når stationen sorterede toget af kvæg fra det nordlige Ukraine og det vestlige Rusland på vej til et nærliggende slagteri. Dette var i sig selv mærkeligt, for slagteriet blev forsynet af gårde, der lå meget tættere på, i Kasakhstan.

Tjernobyl-atomkraftværket eksploderede i 1986, og radioaktivt nedfald gjorde de omkringliggende områder ubeboelige. Store områder i det nordlige Ukraine, Hviderusland og det vestlige Rusland blev forurenet. Med mistanke om høje niveauer af stråling i de ankommende vogne udviklede Sergei en metode til at teste denne teori. Befolkningen blev forbudt at have dosimetre, så Sergei registrerede sig sammen med flere militærmænd på banegården. Efter flere drinks vodka lykkedes det ham at overbevise en soldat om at måle strålingsniveauet i en af ​​de mistænkelige vogne. Det viste sig, at niveauet var flere gange højere end normale værdier.

Ikke alene udsendte kvæget meget stråling, dets niveau var så højt, at det førte til tilfældigt tab af bits i hukommelsen på SM-1800, som var placeret i en bygning ved siden af ​​stationen.

Der var fødevaremangel i USSR, og myndighederne besluttede at blande Tjernobyl-kød med kød fra andre regioner i landet. Dette gjorde det muligt at reducere det samlede niveau af radioaktivitet uden at miste værdifulde ressourcer. Efter at have lært om dette, udfyldte Sergei straks dokumenter til emigration. Og computernedbrud stoppede af sig selv, da strålingsniveauet faldt over tid.

Gennem rørene

Engang skabte Movietech Solutions software til biografer, designet til regnskab, billetsalg og generel ledelse. DOS-versionen af ​​flagskibsappen var ret populær blandt små og mellemstore biografkæder i Nordamerika. Så det er ikke overraskende, at da en Windows 95-version blev annonceret, integreret med de nyeste touchskærme og selvbetjeningskiosker og udstyret med alle mulige rapporteringsværktøjer, blev den også hurtigt populær. Oftest forløb opdateringen uden problemer. Det lokale IT-personale installerede nyt udstyr, migrerede data, og forretningen fortsatte. Undtagen når det ikke varede. Når dette skete, ville firmaet sende James ud, med tilnavnet "The Cleaner."

Selvom kaldenavnet antyder en ondsindet type, er renseren kun en kombination af instruktør, installatør og jack-of-all-trades. James ville tilbringe et par dage på kundens websted med at sætte alle komponenterne sammen, og derefter bruge endnu et par dage på at lære personalet at bruge det nye system, løse eventuelle hardwareproblemer, der opstod, og i det væsentlige hjælpe softwaren gennem dens vorden.

Derfor er det ikke overraskende, at James i disse hektiske tider ankom til kontoret om morgenen, og inden han nåede sit skrivebord, blev han mødt af lederen, fyldt med koffein ud over det sædvanlige.

"Jeg er bange for, at du skal tage til Annapolis, Nova Scotia, så hurtigt som muligt." Hele deres system gik ned, og efter en nats arbejde med deres ingeniører, kan vi ikke finde ud af, hvad der skete. Det ser ud til, at netværket har fejlet på serveren. Men først efter at systemet havde kørt i flere minutter.

- De vendte ikke tilbage til det gamle system? - James svarede fuldstændig seriøst, selvom han mentalt spærrede øjnene op af overraskelse.

— Præcis: deres it-specialist "ændrede prioriteter" og besluttede at forlade med deres gamle server. James, de installerede systemet på seks steder og betalte lige for premium support, og deres forretning drives nu, som det var i 1950'erne.

James rettede sig lidt op.

- Det er en anden sag. Okay, lad os komme i gang.

Da han ankom til Annapolis, var det første, han gjorde, at finde kundens første teater, der havde et problem. På kortet taget i lufthavnen så alt anstændigt ud, men området omkring den ønskede adresse så mistænkeligt ud. Ikke ghetto, men minder om film noir. Da James parkerede ved kantstenen i centrum, henvendte en prostitueret sig til ham. I betragtning af Annapolis's størrelse var det højst sandsynligt den eneste i hele byen. Hendes udseende bragte straks tankerne hen på den berømte karakter, der tilbød sex for penge på det store lærred. Nej, ikke om Julia Roberts, men om Jon Voight [hentydning til filmen "Midnight Cowboy" - ca. bane].

Efter at have sendt den prostituerede på vej, gik James i biografen. Området omkring var blevet bedre, men det gav alligevel indtryk af at være kørt ned. Ikke at James var så bekymret. Han har været elendige steder før. Og det her var Canada, hvor selv røvere er høflige nok til at sige "tak" efter at have taget din tegnebog.

Sideindgangen til biografen var i en fugtig gyde. James gik hen til døren og bankede på. Snart knirkede det og åbnede sig lidt.

-Er du rengøringsassistent? - kom der en hæs stemme indefra.

- Ja, det er mig... Jeg kom for at ordne alt.

James gik ind i biografens lobby. Tilsyneladende ikke havde noget andet valg, begyndte personalet at uddele papirbilletter til besøgende. Dette gjorde finansiel rapportering vanskelig, endsige mere interessante detaljer. Men personalet hilste James med lettelse og tog ham straks med til serverrummet.

Ved første øjekast var alt fint. James loggede ind på serveren og tjekkede de sædvanlige mistænkelige steder. Intet problem. Men af ​​en overflod af forsigtighed lukkede James serveren, udskiftede netværkskortet og rullede systemet tilbage. Hun begyndte straks at arbejde fuldt ud. Personalet begyndte igen at sælge billetter.

James ringede til Mark og informerede ham om situationen. Det er ikke svært at forestille sig, at James måske vil blive ved og se, om der sker noget uventet. Han gik ned af trapperne og begyndte at spørge medarbejderne, hvad der skete. Det er klart, at systemet er holdt op med at fungere. De slukkede og tændte, alt fungerede. Men efter 10 minutter faldt systemet af.

Lige i dette øjeblik skete noget lignende. Pludselig begyndte billetsystemet at kaste fejl. Personalet sukkede og greb papirbilletterne, og James skyndte sig til serverrummet. Alt så godt ud med serveren.

Så kom en af ​​medarbejderne ind.

- Systemet virker igen.

James var forundret, fordi han ikke havde gjort noget. Mere præcist, intet, der ville få systemet til at fungere. Han loggede ud, tog sin telefon og ringede til sit firmas supportlinje. Snart kom den samme medarbejder ind i serverrummet.

- Systemet er nede.

James kiggede på serveren. Et interessant og velkendt mønster af flerfarvede former dansede på skærmen - kaotisk vridende og sammenflettede rør. Vi har alle set denne pauseskærm på et tidspunkt. Det var smukt gengivet og bogstaveligt talt hypnotiserende.


James trykkede på en knap, og mønsteret forsvandt. Han skyndte sig til billetkontoret og mødte på vejen en medarbejder, der vendte tilbage til ham.

- Systemet virker igen.

Hvis du kan lave en mental ansigtspalme, er det præcis, hvad James gjorde. Pauseskærm. Den bruger OpenGL. Og derfor, under drift, bruger den alle ressourcerne fra serverprocessoren. Som et resultat slutter hvert opkald til serveren med en timeout.

James vendte tilbage til serverrummet, loggede ind og erstattede pauseskærmen med de smukke rør med en tom skærm. Det vil sige, at i stedet for en pauseskærm, der bruger 100 % af processorressourcerne, installerede jeg en anden, der ikke bruger ressourcer. Så ventede jeg 10 minutter med at tjekke mit gæt.

Da James ankom til den næste biograf, spekulerede han på, hvordan han skulle forklare sin manager, at han lige havde fløjet 800 km for at slukke pauseskærmen.

Crash under en bestemt fase af månen

Sand historie. En dag opstod der en softwarefejl, der var afhængig af månens fase. Der var en lille rutine, der almindeligvis blev brugt i forskellige MIT-programmer til at beregne tilnærmelsen til Månens sande fase. GLS indbyggede denne rutine i et LISP-program, der, når du skriver en fil, udsender en linje med et tidsstempel på næsten 80 tegn. Det var meget sjældent, at den første linje i en besked ville ende med at blive for lang og føre til den næste linje. Og da programmet senere læste denne fil, bandede den. Længden af ​​den første linje afhang af den nøjagtige dato og klokkeslæt, samt længden af ​​fasespecifikationen på det tidspunkt, tidsstemplet blev udskrevet. Det vil sige, at fejlen bogstaveligt talt afhang af månens fase!

Første papirudgave Jargon fil (Steele-1983) indeholdt et eksempel på en sådan linje, der førte til den beskrevne fejl, men maskinskriveren "rettede" den. Dette er siden blevet beskrevet som en "månefase-fejl".

Vær dog forsigtig med antagelser. For et par år siden stødte ingeniører fra CERN (European Center for Nuclear Research) på fejl i eksperimenter udført på Large Electron-Positron Collider. Da computere aktivt behandler den enorme mængde data, der genereres af denne enhed, før de viser resultatet til videnskabsmænd, spekulerede mange i, at softwaren på en eller anden måde var følsom over for månens fase. Flere desperate ingeniører kom til bunds i sandheden. Fejlen opstod på grund af en lille ændring i geometrien af ​​den 27 km lange ring på grund af Jordens deformation under Månens passage! Denne historie er kommet ind i fysikkens folklore som "Newton's Revenge on Particle Physics" og et eksempel på sammenhængen mellem fysikkens simpleste og ældste love og de mest avancerede videnskabelige begreber.

Ved at skylle toilettet standser toget

Den bedste hardwarefejl, jeg nogensinde har hørt om, var på et højhastighedstog i Frankrig. Fejlen førte til nødbremse af toget, men kun hvis der var passagerer om bord. I hvert sådant tilfælde blev toget taget ud af drift, kontrolleret, men der blev ikke fundet noget. Så blev han sendt tilbage til linjen, og han bragede straks til standsning.

Under en af ​​kontrollerne gik en ingeniør i toget på toilettet. Han skyllede hurtigt væk, BOOM! Nødstop.

Ingeniøren kontaktede chaufføren og spurgte:

– Hvad lavede du lige før du bremsede?

- Nå, jeg satte farten ned på nedstigningen...

Det var mærkeligt, for under normal drift sænker toget farten ved nedkørsler snesevis af gange. Toget kørte videre, og ved næste nedstigning advarede chaufføren:

- Jeg vil sætte farten ned.

Intet skete.

— Hvad gjorde du under den sidste opbremsning? - spurgte chaufføren.

- Nå... jeg var på toilettet...

- Nå, så gå på toilettet og gør, hvad du gjorde, når vi går ned igen!

Ingeniøren gik på toilettet, og da chaufføren advarede: "Jeg sætter farten ned," skyllede han vandet. Selvfølgelig stoppede toget med det samme.

Nu kunne de reproducere problemet og skulle finde årsagen.

Efter to minutter bemærkede de, at motorbremsens fjernbetjeningskabel (toget havde en motor i hver ende) var koblet fra væggen i el-skabet og lå på relæet, der styrede toiletstik-solenoiden... Da relæet var tændt, skabte det interferens i bremsekablet, og systembeskyttelsen mod fejl omfattede simpelthen nødbremsning.

Porten, der hadede FORTRAN

For et par måneder siden bemærkede vi, at netværksforbindelserne på fastlandet [dette var på Hawaii] blev meget, meget langsomme. Dette kan vare i 10-15 minutter og så pludselig opstå igen. Efter nogen tid, klagede min kollega til mig, at netværksforbindelserne på fastlandet generelt virker ikke. Han havde en eller anden FORTRAN-kode, der skulle kopieres til en maskine på fastlandet, men det kunne den ikke, fordi "netværket ikke holdt længe nok til, at FTP-uploadet kunne fuldføre."

Ja, det viste sig, at der opstod netværksfejl, da en kollega forsøgte at FTP en fil med kildekode i FORTRAN til en maskine på fastlandet. Vi forsøgte at arkivere filen: så blev den kopieret glat (men målmaskinen havde ikke en udpakker, så problemet blev ikke løst). Til sidst "delte" vi FORTRAN-koden i meget små stykker og sendte dem én ad gangen. De fleste af fragmenterne blev kopieret uden problemer, men nogle få stykker bestod ikke, eller bestod efter talrige forsøg.

Da vi undersøgte de problematiske passager, opdagede vi, at de havde noget til fælles: De indeholdt alle kommentarblokke, der begyndte og sluttede med linjer bestående af stort C (som en kollega foretrak at kommentere i FORTRAN). Vi mailede netværkseksperter på fastlandet og bad om hjælp. Selvfølgelig ville de se prøver af vores filer, der ikke kunne overføres via FTP... men vores breve nåede dem ikke. Til sidst kom vi frem til en simpel beskrivehvordan ikke-overførbare filer ser ud. Det virkede :) [Tør jeg tilføje et eksempel på en af ​​de problematiske FORTRAN-kommentarer her? Sandsynligvis ikke det værd!]

Til sidst lykkedes det os at finde ud af det. En ny gateway blev for nylig installeret mellem vores del af campus og fastlandsnetværket. Det havde KÆMPE svært ved at sende pakker, der indeholdt gentagne bits med store bogstaver C! Kun nogle få af disse pakker kunne optage alle gateway-ressourcerne og forhindre de fleste andre pakker i at komme igennem. Vi klagede til gateway-producenten... og de svarede: "Åh, ja, du står over for en fejl med gentagne C! Vi kender allerede til ham." Vi løste til sidst problemet ved at købe en ny gateway fra en anden producent (til førstnævntes forsvar kan manglende evne til at overføre FORTRAN-programmer være en fordel for nogle!).

Hårde tider

For et par år siden, mens jeg arbejdede på at skabe et ETL-system i Perl for at reducere omkostningerne til fase 40 kliniske forsøg, skulle jeg behandle omkring 000 datoer. To af dem bestod ikke testen. Dette generede mig ikke så meget, fordi disse datoer blev taget fra klient-leverede data, som ofte, skal vi sige, var overraskende. Men da jeg tjekkede de originale data, viste det sig, at disse datoer var 1. januar 2011 og 1. januar 2007. Jeg troede, at fejlen var indeholdt i det program, jeg lige havde skrevet, men det viste sig, at det allerede var 30 år. gammel. Dette kan lyde mystisk for dem, der ikke er bekendt med software-økosystemet. På grund af et andet firmas langvarige beslutning om at tjene penge, betalte min klient mig for at rette en fejl, som det ene firma havde introduceret ved et uheld og det andet med vilje. For at du skal forstå, hvad jeg taler om, er jeg nødt til at tale om virksomheden, der tilføjede den funktion, der endte med at blive en fejl, samt et par andre interessante begivenheder, der bidrog til den mystiske fejl, jeg fik rettet.

I de gode gamle dage nulstillede Apple-computere nogle gange spontant deres dato til 1. januar 1904. Årsagen var enkel: den brugte et batteridrevet "systemur" til at holde styr på dato og klokkeslæt. Hvad skete der, da batteriet døde? Computere begyndte at spore datoen med antallet af sekunder siden begyndelsen af ​​en epoke. Med epoke mente vi den oprindelige referencedato, og for Macintoshes var den 1. januar 1904. Og efter at batteriet døde, blev den aktuelle dato nulstillet til den angivne. Men hvorfor skete dette?

Tidligere brugte Apple 32 bit til at gemme antallet af sekunder siden den oprindelige dato. En bit kan gemme en af ​​to værdier - 1 eller 0. To bit kan gemme en af ​​fire værdier: 00, 01, 10, 11. Tre bit - en værdi ud af otte: 000, 001, 010, 011, 100 , 101, 110, 111 osv. Og 32 kunne gemme en af ​​232 værdier, det vil sige 4 sekunder. For Apple-datoer svarede dette til omkring 294 år, så ældre Mac'er kan ikke klare datoer efter 967. Og hvis systembatteriet dør, nulstilles datoen til 296 sekunder siden begyndelsen af ​​epoken, og du skal manuelt indstille datoen, hver gang du tænder for computeren (eller indtil du køber et nyt batteri).

Apples beslutning om at gemme datoer som sekunder siden epoken betød dog, at vi ikke kunne håndtere datoer før epoken, hvilket havde vidtrækkende konsekvenser, som vi skal se. Apple introducerede en funktion, ikke en fejl. Det betød blandt andet, at Macintosh-operativsystemet var immunt over for "millennium-fejlen" (hvilket ikke kunne siges om mange Mac-programmer, der havde deres egne datosystemer til at omgå restriktioner).

Fortsæt. Vi brugte Lotus 1-2-3, IBM's "killer-applikation", der var med til at lancere pc-revolutionen, selvom Apple-computere havde VisiCalc, som gjorde den personlige computer til en succes. Retfærdigvis, hvis 1-2-3 ikke var dukket op, ville pc'er næppe have taget fart, og personlige computeres historie kunne have udviklet sig meget anderledes. Lotus 1-2-3 behandlede forkert 1900 som et skudår. Da Microsoft udgav sit første regneark, Multiplan, erobrede det en lille del af markedet. Og da de lancerede Excel-projektet, besluttede de ikke kun at kopiere række- og kolonnenavneskemaet fra Lotus 1-2-3, men også at sikre fejlkompatibilitet ved bevidst at behandle 1900 som et skudår. Dette problem eksisterer stadig i dag. Det vil sige, i 1-2-3 var dette en fejl, men i Excel var det en bevidst beslutning, der sikrede, at alle 1-2-3 brugere kunne importere deres tabeller til Excel uden at ændre dataene, selvom de var forkerte.

Men der var et andet problem. Først udgav Microsoft Excel til Macintosh, som ikke genkendte datoer før 1. januar 1904. Og i Excel blev 1. januar 1900 betragtet som begyndelsen på æraen. Derfor lavede udviklerne en ændring, så deres program genkendte typen af ​​æra og lagrede data i sig selv i overensstemmelse med den ønskede æra. Microsoft skrev endda en forklarende artikel om dette. Og denne beslutning førte til min fejl.

Mit ETL-system modtog Excel-regneark fra kunder, der var oprettet på Windows, men som også kunne oprettes på en Mac. Derfor kunne begyndelsen af ​​æraen i tabellen enten være 1. januar 1900 eller 1. januar 1904. Hvordan finder man ud af det? Excel-filformatet viser de nødvendige oplysninger, men den parser, jeg brugte, viste det ikke (nu gør det det), og antog, at du kender epoken for en bestemt tabel. Jeg kunne nok have brugt mere tid på at forstå det binære Excel-format og sende en patch til parserforfatteren, men jeg havde meget mere at gøre for klienten, så jeg skrev hurtigt en heuristik for at bestemme epoken. Hun var simpel.

I Excel kan datoen 5. juli 1998 repræsenteres i formatet "07-05-98" (ubrugeligt amerikansk system), "5. juli 98", "5. juli 1998", "5-jul-98" eller et andet format, et andet ubrugeligt format (ironisk nok var et af de formater, min version af Excel ikke tilbød, ISO 8601). Men i tabellen blev den uformaterede dato gemt som enten "35981" for epoke-1900 eller "34519" for epoke-1904 (tallene repræsenterer antallet af dage siden epoken). Jeg brugte simpelthen en simpel parser til at udtrække året fra den formaterede dato, og brugte derefter Excel-parseren til at udtrække året fra den uformaterede dato. Hvis begge værdier afveg med 4 år, så vidste jeg, at jeg brugte et system med epoke-1904.

Hvorfor brugte jeg ikke bare formaterede datoer? Fordi den 5. juli 1998 kan formateres som "Juli, 98" med tabt dag i måneden. Vi modtog borde fra så mange virksomheder, der lavede dem på så mange forskellige måder, at det var op til os (i dette tilfælde mig) at finde ud af datoerne. Desuden, hvis Excel får det rigtige, så skal vi det også!

Samtidig stødte jeg på 39082. Lad mig minde dig om, at Lotus 1-2-3 betragtede 1900 som et skudår, og dette blev trofast gentaget i Excel. Og da dette tilføjede en dag til år 1900, kunne mange datoberegningsfunktioner være forkerte for netop den dag. Det vil sige, at 39082 kunne have været 1. januar 2011 (på Mac) eller 31. december 2006 (på Windows). Hvis min "årsparser" udtog år 2011 fra den formaterede værdi, så er alt fint. Men da Excel-parseren ikke ved, hvilken epoke der bruges, er den som standard epoke-1900, og returnerer året 2006. Min ansøgning så, at forskellen var 5 år, betragtede det som en fejl, loggede det og returnerede en uformateret værdi.

For at komme uden om dette skrev jeg dette (pseudokode):

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

Og så blev alle 40 datoer parset korrekt.

Midt i store printjobs

I begyndelsen af ​​1980'erne arbejdede min far hos Storage Technology, en nu hedengangne ​​afdeling, der skabte båndstationer og pneumatiske systemer til højhastighedsbåndfremføring.

De redesignede drevene, så de kunne have ét centralt "A"-drev forbundet til syv "B"-drev, og det lille OS i RAM, der styrede "A"-drevet, kunne uddelegere læse- og skriveoperationer til alle "B"-drevene.

Hver gang drev "A" blev startet, var det nødvendigt at indsætte en diskette i det perifere drev, der var tilsluttet "A", for at indlæse operativsystemet i dets hukommelse. Det var ekstremt primitivt: computerkraft blev leveret af en 8-bit mikrocontroller.

Målgruppen for sådant udstyr var virksomheder med meget store datavarehuse - banker, detailkæder osv. - som skulle udskrive en masse adresseetiketter eller kontoudtog.

En klient havde et problem. Midt i et udskriftsjob kan et bestemt drev "A" holde op med at fungere, hvilket får hele jobbet til at gå i stå. For at genoprette driften af ​​drevet var personalet nødt til at genstarte alt. Og hvis dette skete midt i en seks-timers opgave, så gik en enorm mængde dyr computertid tabt, og tidsplanen for hele operationen blev forstyrret.

Teknikere blev sendt fra Storage Technologies. Men på trods af deres bedste anstrengelser var de ikke i stand til at reproducere fejlen under testforhold: det så ud til at ske midt i store printjob. Problemet var ikke hardwaren, de erstattede alt, hvad de kunne: RAM, mikrocontroller, diskettedrev, alle tænkelige dele af bånddrevet - problemet varede ved.

Så ringede teknikerne til hovedkvarteret og ringede til Eksperten.

Eksperten greb en stol og en kop kaffe, satte sig i computerrummet – dengang var der lokaler dedikeret til computere – og så på, hvordan personalet stod i kø for et stort printjob. Eksperten ventede på, at der skulle ske en fejl - og det skete. Alle kiggede på eksperten, men han anede ikke, hvorfor det skete. Så han beordrede jobbet i kø igen, og alle ansatte og teknikere vendte tilbage til arbejdet.

Eksperten satte sig igen i stolen og begyndte at vente på en fiasko. Der gik omkring seks timer, og fejlen opstod. Eksperten havde igen ingen idéer, bortset fra at alt skete i et rum fyldt med mennesker. Han beordrede missionen genstartet, satte sig tilbage og ventede.

Ved den tredje fejl bemærkede eksperten noget. Fejlen opstod, da personalet skiftede bånd i et fremmed drev. Desuden opstod fejlen, så snart en af ​​medarbejderne gik gennem en bestemt flise på gulvet.

Det hævede gulv var lavet af aluminiumsfliser lagt i en højde på 6 til 8 tommer. Adskillige ledninger fra computere løb under det hævede gulv for at forhindre, at nogen ved et uheld træder på et vigtigt kabel. Fliserne blev lagt meget tæt for at forhindre snavs i at komme ind under det hævede gulv.

Eksperten indså, at en af ​​fliserne var deformeret. Da en medarbejder trådte på dets hjørne, gned flisens kanter mod de tilstødende fliser. Plastdelene, der forbandt fliserne, gned også med dem, hvilket forårsagede statiske mikroudladninger, der skabte radiofrekvensinterferens.

I dag er RAM meget bedre beskyttet mod radiofrekvensinterferens. Men i de år var det ikke tilfældet. Eksperten indså, at denne interferens forstyrrede hukommelsen og dermed driften af ​​operativsystemet. Han ringede til supporttjenesten, bestilte nye fliser, installerede dem selv, og problemet forsvandt.

Det er højvande!

Historien fandt sted i et serverrum, på fjerde eller femte sal i et kontor i Portsmouth (tror jeg), i havneområdet.

En dag styrtede Unix-serveren med hoveddatabasen ned. De genstartede ham, men han fortsatte lykkeligt med at falde igen og igen. Vi besluttede at ringe til en fra supporttjenesten.

Supporteren... Jeg tror, ​​han hed Mark, men det gør ikke noget... Jeg tror ikke, jeg kender ham. Det er lige meget, egentlig. Lad os holde med Mark, okay? Store.

Så et par timer senere ankom Mark (det er ikke langt fra Leeds til Portsmouth, du ved), tændte serveren og alt fungerede uden problemer. Typisk forbandet support, klienten bliver meget ked af det. Mark kigger gennem logfilerne og finder intet uheldigt. Så Mark stiger tilbage på toget (eller hvilken transportform han end ankom med, det kunne have været en halt ko for alt, hvad jeg ved... i hvert fald, det gør ikke noget, okay?) og går tilbage til Leeds, efter at have spildt dagen.

Samme aften går serveren ned igen. Historien er den samme... serveren rejser sig ikke. Mark forsøger at hjælpe eksternt, men klienten kan ikke starte serveren.

Endnu et tog, bus, citronmarengs eller andet lort, og Mark er tilbage i Portsmouth. Se, serveren starter uden problemer! Mirakel. Mark bruger flere timer på at tjekke, at alt er i orden med styresystemet eller softwaren og tager af sted til Leeds.

Omkring midten af ​​dagen går serveren ned (tag det roligt!). Denne gang virker det rimeligt at hente hardwaresupportfolk til at erstatte serveren. Men nej, efter cirka 10 timer falder den også.

Situationen gentog sig i flere dage. Serveren virker, går ned efter cirka 10 timer og starter ikke i de næste 2 timer. De tjekkede køling, hukommelseslækager, de tjekkede alt, men fandt intet. Så stoppede nedbruddene.

Ugen forløb ubekymret... alle var glade. Glad indtil det hele starter igen. Billedet er det samme. 10 timers arbejde, 2-3 timers nedetid...

Og så sagde nogen (jeg tror, ​​de fortalte mig, at denne person ikke havde noget med IT at gøre):

"Det er tidevandet!"

Udråbet blev mødt med tomme blikke, og nogens hånd tøvede sandsynligvis ved sikkerhedsopkaldsknappen.

"Det holder op med at arbejde med tidevandet."

Dette synes at være et helt fremmed koncept for IT-supportmedarbejdere, som næppe læser Tide Yearbook, mens de sidder ned til kaffen. De forklarede, at dette ikke kunne relateres til tidevandet på nogen måde, fordi serveren havde arbejdet i en uge uden fejl.

"I sidste uge var tidevandet lavt, men i denne uge er det højt."

Lidt terminologi for dem, der ikke har en lystbådelicens. Tidevandet afhænger af månens cyklus. Og når Jorden roterer, skaber tyngdekraften fra Solen og Månen hver 12,5 time en flodbølge. I begyndelsen af ​​den 12,5 timer lange cyklus er der højvande, midt i cyklussen er der ebbe, og i slutningen er der igen højvande. Men i takt med at månens kredsløb ændrer sig, ændres forskellen mellem lavvande og højvande også. Når Månen er mellem Solen og Jorden eller på den modsatte side af Jorden (fuldmåne eller ingen måne), får vi Syzygyn tidevand – det højeste højvande og det laveste lavvande. Ved halvmåne får vi kvadraturtidevand - det laveste tidevand. Forskellen mellem de to yderpunkter falder meget. Månecyklussen varer 28 dage: syzygian - kvadratur - syzygian - kvadratur.

Da teknikerne fik forklaret essensen af ​​tidevandskræfter, tænkte de straks, at de skulle tilkalde politiet. Og ganske logisk. Men det viser sig, at fyren havde ret. To uger tidligere fortøjede en destroyer ikke langt fra kontoret. Hver gang tidevandet hævede det til en vis højde, endte skibets radarpost i niveau med serverrummets gulv. Og radaren (eller elektronisk krigsførelsesudstyr eller andet militærlegetøj) skabte kaos i computerne.

Flyvemission for raketten

Jeg fik til opgave at overføre et stort (ca. 400 tusind linjer) raketopsendelseskontrol- og overvågningssystem til nye versioner af operativsystemet, compileren og sproget. Mere præcist, fra Solaris 2.5.1 til Solaris 7 og fra Verdix Ada Development System (VADS), skrevet i Ada 83, til Rational Apex Ada-systemet, skrevet i Ada 95. VADS blev købt af Rational, og dets produkt blev forældet, selvom Rational forsøgte at implementere kompatible versioner af VADS-specifikke pakker for at lette overgangen til Apex-kompileren.

Tre personer hjalp mig med at få koden kompileret rent. Det tog to uger. Og så arbejdede jeg på egen hånd for at få systemet til at fungere. Kort sagt var det den værste arkitektur og implementering af et softwaresystem, jeg havde stødt på, så det tog yderligere to måneder at færdiggøre porten. Systemet blev derefter sendt til test, hvilket tog flere måneder. Jeg rettede straks de fejl, der blev fundet under testen, men antallet af dem faldt hurtigt (kildekoden var et produktionssystem, så dets funktionalitet fungerede ret pålideligt, jeg skulle bare fjerne de fejl, der opstod under tilpasningen til den nye compiler). Til sidst, da alt fungerede, som det skulle, blev jeg overført til et andet projekt.

Og fredagen før Thanksgiving ringede telefonen.

Raketopsendelsen skulle testes om cirka tre uger, og under laboratorietest af nedtællingen blev rækkefølgen af ​​kommandoer blokeret. I det virkelige liv ville dette afbryde testen, og hvis blokeringen opstod inden for få sekunder efter start af motoren, ville der ske adskillige irreversible handlinger i hjælpesystemerne, hvilket ville kræve en lang - og dyr - beredskab af raketten. Det ville ikke være startet, men mange mennesker ville have været meget kede af tabet af tid og en masse, mange penge. Lad ikke nogen fortælle dig, at forsvarsministeriet bruger penge hensynsløst - jeg har aldrig mødt en kontraktchef, der ikke satte budget først eller anden, efterfulgt af tidsplan.

I de foregående måneder var denne nedtællingsudfordring blevet kørt hundredvis af gange i mange variationer, med kun et par mindre hikke. Så sandsynligheden for, at dette skete, var meget lav, men dets konsekvenser var meget betydelige. Multiplicer begge disse faktorer, og du vil forstå, at nyhederne forudsagde en ødelagt ferieuge for mig og snesevis af ingeniører og ledere.

Og opmærksomheden blev givet til mig som den person, der porterede systemet.

Som med de fleste sikkerhedskritiske systemer blev der logget mange parametre, så det var ret nemt at identificere de få linjer kode, der blev eksekveret, før systemet styrtede ned. Og selvfølgelig var der absolut intet usædvanligt ved dem; de samme udtryk var blevet udført med succes bogstaveligt talt tusindvis af gange i løbet af det samme løb.

Vi kaldte folk fra Apex til Rational, fordi det var dem, der udviklede compileren, og nogle af de rutiner, de udviklede, blev kaldt i den mistænkelige kode. De (og alle andre) var imponerede over, at der var behov for at komme til roden af ​​et problem af bogstavelig talt national betydning.

Da der ikke var noget interessant i journalerne, besluttede vi at forsøge at reproducere problemet i et lokalt laboratorium. Dette var ikke en let opgave, da hændelsen fandt sted cirka én gang pr. 1000 løb. En formodet årsag var, at et opkald til en leverandørudviklet mutex-funktion (en del af VADS-migreringspakken) Unlock førte ikke til oplåsning. Behandlingstråden, der kaldte funktionen, behandlede hjerteslagsmeddelelser, som nominelt ankom hvert sekund. Vi hævede frekvensen til 10 Hz, det vil sige 10 gange i sekundet, og begyndte at løbe. Cirka en time senere låste systemet sig selv. I loggen så vi, at rækkefølgen af ​​optagede beskeder var den samme som under den mislykkede test. Vi kørte flere løb mere, systemet var konsekvent blokeret 45-90 minutter efter starten, og hver gang indeholdt loggen den samme rute. Selvom vi teknisk set kørte forskellig kode - meddelelsesfrekvensen var anderledes - var systemets opførsel den samme, så vi var sikre på, at dette indlæsningsscenarie forårsagede det samme problem.

Nu skulle vi finde ud af, hvor præcis blokeringen fandt sted i rækkefølgen af ​​udtryk.

Denne implementering af systemet brugte Ada opgavesystemet og brugte det utrolig dårligt. Opgaver er en samtidig eksekverbar konstruktion på højt niveau i Ada, noget i retning af udførelsestråde, kun indbygget i selve sproget. Når to opgaver skal kommunikere, "sætter de et møde", udveksler de nødvendige data og stopper derefter mødet og vender tilbage til deres uafhængige henrettelser. Systemet blev dog implementeret anderledes. Efter at en målopgave var rendezvous, mødtes denne målopgave med en anden opgave, som derefter mødtes med en tredje opgave, og så videre, indtil en vis behandling var afsluttet. Herefter blev alle disse rendezvous afsluttet, og hver opgave skulle vende tilbage til sin udførelse. Det vil sige, at vi havde at gøre med det dyreste funktionsopkaldssystem i verden, som stoppede hele "multitasking"-processen, mens det behandlede en del af inputdataene. Og før førte dette ikke til problemer, kun fordi gennemstrømningen var meget lav.

Jeg beskrev denne opgavemekanisme, fordi når et rendezvous blev anmodet om eller forventet at fuldføre, kunne der opstå et "opgaveskifte". Det vil sige, at processoren kunne begynde at behandle en anden opgave, der er klar til at blive udført. Det viser sig, at når en opgave er klar til at mødes med en anden opgave, kan en helt anden opgave begynde at udføre, og til sidst vender kontrollen tilbage til det første møde. Og andre hændelser kan forekomme, der får opgaven til at skifte; en sådan hændelse er et kald til en systemfunktion, såsom udskrivning eller udførelse af en mutex.

For at forstå, hvilken linje kode der forårsagede problemet, var jeg nødt til at finde en måde at registrere fremskridt gennem en sekvens af udsagn uden at udløse en opgaveskift, hvilket ville forhindre et nedbrud i at opstå. Så jeg kunne ikke udnytte det Put_Line()for at undgå at udføre I/O-operationer. Jeg kunne indstille en tællervariabel eller noget lignende, men hvordan kan jeg se dens værdi, hvis jeg ikke kan vise den på skærmen?

Også ved undersøgelse af loggen viste det sig, at på trods af fastfrysningen i behandlingen af ​​hjerteslagsmeddelelser, som blokerede alle I/O-operationer af processen og forhindrede anden behandling i at blive udført, fortsatte andre uafhængige opgaver med at blive udført. Det vil sige, at arbejdet ikke var fuldstændig blokeret, kun en (kritisk) kæde af opgaver.

Dette var det spor, der var nødvendigt for at evaluere det blokerende udtryk.

Jeg lavede en Ada-pakke, der indeholdt en opgave, en opregnet type og en global variabel af den type. Utallige bogstaver var bundet til specifikke udtryk for den problematiske sekvens (f.eks. Incrementing_Buffer_Index, Locking_Mutex, Mutex_Unlocked), og indsatte derefter tildelingsudtryk i den, der tildelte den tilsvarende opregning til en global variabel. Da objektkoden for alt dette simpelthen lagrede en konstant i hukommelsen, var opgaveskift som følge af dens udførelse ekstremt usandsynligt. Vi var primært mistænksomme over for udtryk, der kunne skifte opgaven, da blokeringen skete ved udførelse i stedet for at vende tilbage, når opgaven skiftede tilbage (af flere årsager).

Sporingsopgaven kørte simpelthen i en løkke og tjekkede periodisk for at se, om værdien af ​​den globale variabel var ændret. Ved hver ændring blev værdien gemt i en fil. Så en kort ventetid og et nyt tjek. Jeg skrev variablen til filen, fordi opgaven kun blev udført, da systemet valgte den til udførelse, da opgaven blev ændret i problemområdet. Uanset hvad der skete i denne opgave, ville det ikke påvirke andre, ikke-relaterede blokerede opgaver.

Det var forventet, at når systemet nåede det punkt, hvor den problematiske kode blev eksekveret, ville den globale variabel blive nulstillet, når man flyttede til hvert næste udtryk. Så vil der ske noget, der får opgaven til at skifte, og da dens udførelsesfrekvens (10 Hz) er lavere end overvågningsopgavens, kunne monitoren fange værdien af ​​den globale variabel og skrive den. I en normal situation kunne jeg få en gentagen sekvens af en delmængde af opregninger: de sidste værdier af variablen på tidspunktet for opgaveskiftet. Når den hænger, skal den globale variabel ikke længere ændre sig, og den sidst skrevet værdi vil indikere, hvilket udtryk der ikke blev fuldført.

Jeg kørte koden med sporing. Han frøs. Og overvågningen fungerede som smurt.

Loggen indeholdt den forventede sekvens, som blev afbrudt af en værdi, der indikerede, at en mutex var blevet kaldt Unlock, og opgaven er ikke afsluttet - som det er tilfældet med tusindvis af tidligere opkald.

Apex-ingeniører var febrilsk ved at analysere deres kode på dette tidspunkt og fandt et sted i mutex'en, hvor der teoretisk set kunne opstå en låsning. Men dens sandsynlighed var meget lav, da kun en bestemt række af begivenheder, der fandt sted på et bestemt tidspunkt, kunne føre til blokering. Murphys lov, gutter, det er Murphys lov.

For at beskytte det stykke kode, jeg havde brug for, erstattede jeg mutex-funktionskaldene (bygget oven på OS's mutex-funktionalitet) med en lille indbygget Ada mutex-pakke for at kontrollere mutex-adgang til det stykke.

Jeg indsatte det i koden og kørte testen. Syv timer senere virkede koden stadig.

Min kode blev indsendt til Rational, hvor de kompilerede den, adskilte den og tjekkede, at den ikke brugte den samme tilgang, som blev brugt i de problematiske mutex-funktioner.

Dette var den mest overfyldte kodegennemgang i min karriere 🙂 Der var omkring ti ingeniører og ledere i rummet sammen med mig, yderligere ti personer var på telefonkonference - og de undersøgte alle omkring 20 linjer kode.

Koden blev gennemgået, nye eksekverbare filer blev samlet og indsendt til formel regressionstest. Et par uger senere lykkedes nedtællingstesten, og raketten lettede.

Okay, det er godt og vel, men hvad er meningen med historien?

Det var et helt ulækkert problem. Hundredtusindvis af linjer kode, parallel eksekvering, over et dusin interagerende processer, dårlig arkitektur og dårlig implementering, grænseflader til indlejrede systemer og brugt millioner af dollars. Intet pres, vel.

Jeg var ikke den eneste, der arbejdede på dette problem, selvom jeg var i søgelyset, da jeg lavede porteringen. Men selvom jeg gjorde det, betyder det ikke, at jeg forstod alle de hundredtusindvis af linjer kode, eller endda skummede dem. Koden og logfilerne blev analyseret af ingeniører over hele landet, men da de fortalte mig deres hypoteser om årsagerne til fejlen, tog det mig kun et halvt minut at tilbagevise dem. Og da jeg blev bedt om at analysere teorier, ville jeg give det videre til en anden, for det var tydeligt for mig, at disse ingeniører gik den forkerte vej. Lyder det overmodigt? Ja, det er sandt, men jeg afviste hypoteserne og anmodningerne af en anden grund.

Jeg forstod problemets natur. Jeg vidste ikke præcis, hvor det skete eller hvorfor, men jeg vidste, hvad der skete.

Gennem årene har jeg oparbejdet en masse viden og erfaring. Jeg var en af ​​pionererne inden for at bruge Ada og forstod dets fordele og ulemper. Jeg ved, hvordan Ada runtime-bibliotekerne håndterer opgaver og håndterer parallel eksekvering. Og jeg forstår lav-niveau programmering på niveau med hukommelse, registre og assembler. Jeg har med andre ord dyb viden inden for mit felt. Og jeg brugte dem til at finde årsagen til problemet. Jeg arbejdede ikke bare uden om fejlen, jeg forstod, hvordan man fandt den i et meget følsomt runtime-miljø.

Sådanne historier om kamp med kode er ikke særlig interessante for dem, der ikke er bekendt med funktionerne og betingelserne for en sådan kamp. Men disse historier hjælper os med at forstå, hvad der skal til for at løse virkelig svære problemer.

For at løse virkelig svære problemer skal du være mere end blot en programmør. Du skal forstå kodens "skæbne", hvordan den interagerer med omgivelserne, og hvordan selve miljøet fungerer.

Og så får du din egen ødelagte ferieuge.

Fortsættes.

Kilde: www.habr.com

Tilføj en kommentar