Programozók és mérnökök folklórja (1. rész)

Programozók és mérnökök folklórja (1. rész)

Ez az internetről szóló történetek gyűjteménye arról, hogy a hibák néha teljesen hihetetlen megnyilvánulásokkal rendelkeznek. Talán neked is van mondanivalód.

Autó allergia vanília fagylaltra

Egy történet azoknak a mérnököknek, akik megértik, hogy nem mindig a nyilvánvaló a megoldás, és bármennyire is valószínűtlennek tűnnek a tények, azok továbbra is tények. A General Motors Corporation Pontiac részlegéhez panasz érkezett:

Másodszor írok neked, és nem hibáztatlak, hogy nem válaszoltál, mert őrülten hangzik. Családunknak hagyománya van: minden este vacsora után fagyi van. A fagylaltfajták minden alkalommal változnak, vacsora után az egész család választja ki, hogy melyik fagylaltot vegye meg, utána megyek a boltba. Nemrég vettem egy új Pontiac-ot, és azóta gondot okoznak a fagylaltozásaim. Valahányszor veszek vaníliafagyit és visszajövök a boltból, nem indul el az autó. Ha hozok más fagyit, akkor gond nélkül indul az autó. Szeretnék egy komoly kérdést feltenni, bármennyire is hülyén hangzik: "Mi az a Pontiac, ami miatt nem indul be, ha vaníliafagyit hozok, hanem könnyen beindul, ha más ízű fagyit hozok?".

Képzelheti, hogy a szakosztály elnöke szkeptikusan fogadta a levelet. Azonban minden esetre elküldött egy mérnököt, hogy ellenőrizze. Meglepte, hogy egy jómódú, jól képzett, gyönyörű környéken élő férfi találkozott vele. Megállapodtak, hogy vacsora után találkoznak, hogy együtt menjenek el a fagylaltozóba. Aznap este vanília volt, és amikor visszaültek a kocsiba, nem indult el.

A mérnök még három este jött. A fagylalt először csokis volt. Az autó elindult. A második alkalom eperfagylalt volt. Az autó elindult. A harmadik este vaníliát kért. Az autó nem indult be.

A mérnök józan ésszel nem volt hajlandó elhinni, hogy az autó allergiás a vaníliafagylaltra. Ezért megegyeztem az autó tulajdonosával, hogy addig folytatja látogatásait, amíg nem talál megoldást a problémára. Útközben pedig jegyzetelni kezdett: felírt minden információt, a napszakot, a benzin típusát, az érkezési és az üzletből való visszaérkezés időpontját stb.

A mérnök hamar rájött, hogy az autó tulajdonosa kevesebb időt töltött a vaníliafagylalt vásárlásával. Az ok az áruk bolti elrendezése volt. A vaníliafagylalt volt a legnépszerűbb, és az üzlet elején külön mélyhűtőben tárolták, hogy könnyebben megtalálják. És az összes többi fajta a bolt hátsó részében volt, és sokkal több időbe telt megtalálni a megfelelő fajtát és fizetni.

Most az volt a kérdés a mérnöknek: miért nem indult be az autó, ha kevesebb idő telt el a motor leállítása óta? Mivel a probléma az idővel volt, nem a vaníliafagylalttal, a mérnök gyorsan megtalálta a választ: gázzár volt. Minden este előfordult, de amikor az autó tulajdonosa több időt töltött fagylalt keresésével, a motornak volt ideje kellően lehűlni és simán beindulni. És amikor egy férfi vanília fagylaltot vásárolt, a motor még mindig túl meleg volt, és a gázdugónak nem volt ideje feloldódni.

Morális: a teljesen őrült problémák is néha valósak.

Crash Bandicoot

Fájdalmas ezt átélni. Programozóként megszokod, hogy a kódodat hibáztatod először, másodszor, harmadszor... és valahol a tízezredik helyen a fordítót hibáztatod. És még lejjebb a listán már a berendezést hibáztatja.

Íme az én történetem a vasbogárról.

A Crash Bandicoot játékhoz kódot írtam a betöltéshez és a memóriakártyára mentéshez. Egy ilyen önelégült játékfejlesztő számára ez olyan volt, mint egy séta a parkban: gondoltam, hogy a munka több napig tart. Végül azonban hat hétig hibakerestem a kódot. Útközben más problémákat is megoldottam, de néhány naponta több órára visszatértem ehhez a kódhoz. Agónia volt.

A tünet a következőképpen nézett ki: amikor elmenti a játék aktuális szakaszát és hozzáfér a memóriakártyához, szinte mindig minden rendben megy... De néha az olvasási vagy írási művelet nyilvánvaló ok nélkül lejár. A rövid felvétel gyakran károsítja a memóriakártyát. Amikor egy játékos menteni próbál, nemcsak hogy nem ment, hanem a térképet is elpusztítja. Szar.

Egy idő után a Sony producerünk, Connie Bus pánikba esett. Nem tudtuk elküldeni a játékot ezzel a hibával, és hat héttel később nem értettem, mi okozza a problémát. Connie-n keresztül felvettük a kapcsolatot más PS1 fejlesztőkkel: tapasztalt valaki ilyet? Nem. Senkinek nem volt gondja a memóriakártyával.

Ha kifogytak az ötletek a hibakereséshez, gyakorlatilag ez az egyetlen „oszd meg és uralkodj” módszer marad: egyre több kódot távolítasz el a hibás programból, amíg nem lesz egy viszonylag kis töredék, ami továbbra is problémát okoz. Vagyis levágsz egy darabot a programból, amíg a hibát tartalmazó rész meg nem marad.

De a helyzet az, hogy nagyon nehéz darabokat kivágni egy videojátékból. Hogyan kell futtatni, ha eltávolította a gravitációt emuláló kódot? Vagy karaktereket rajzolni?

Tehát teljes modulokat kell lecserélnie olyan csonkokra, amelyek úgy tesznek, mintha valami hasznosat csinálnának, de valójában valami nagyon egyszerű dolgot csinálnak, ami nem tartalmazhat hibákat. Ilyen mankókat kell írni, hogy legalább működjön a játék. Ez egy lassú és fájdalmas folyamat.

Röviden: megcsináltam. Egyre több kódrészletet távolítottam el, mígnem megmaradt a kezdeti kód, ami beállítja a rendszert a játék indítására, inicializálja a renderelő hardvert stb. Természetesen ebben a szakaszban nem tudtam mentés és betöltés menüt készíteni, mert az összes grafikus kódhoz egy csonkot kell készítenem. De tudnék úgy tenni, mintha olyan felhasználó lennék, aki a (láthatatlan) mentési és betöltési képernyőt használja, és kéri, hogy mentse, majd írjon a memóriakártyára.

Ennek eredményeként maradt egy kis kódrészlet, amiben még mindig az előbb említett probléma volt - de ez eddig véletlenszerűen történt! Legtöbbször minden jól működött, de néha voltak hibák. Szinte az összes játékkódot eltávolítottam, de a hiba továbbra is élt. Elgondolkodtató volt: a kód többi része nem igazán csinált semmit.

Valamikor, valószínűleg hajnali háromkor, eszembe jutott egy gondolat. Az olvasási és írási (I/O) műveletek pontos végrehajtási időt jelentenek. Ha merevlemezzel, memóriakártyával vagy Bluetooth-modullal dolgozik, az olvasásért és írásért felelős alacsony szintű kód ezt az órajel impulzusainak megfelelően végzi.

Az óra segítségével a processzorhoz közvetlenül nem csatlakozó eszköz szinkronizálódik a processzorban futó kóddal. Az óra határozza meg az adatátviteli sebességet - az adatátviteli sebességet. Ha zavar van az időzítésekkel, akkor vagy a hardver, vagy a szoftver, vagy mindkettő összekeveredett. És ez nagyon rossz, mert az adatok megsérülhetnek.

Mi van, ha valami a kódunkban összezavarja az időzítést? A tesztprogram kódjában mindent átnéztem, ami ezzel kapcsolatos, és azt vettem észre, hogy a PS1-ben a programozható időzítőt 1 kHz-es (1000 ciklus/másodperc) frekvenciára állítottuk. Ez elég sok, alapból a set-top box indításakor 100 Hz-es frekvencián fut. És a legtöbb játék ezt a frekvenciát használja.

Andy, a játék fejlesztője az időzítőt 1 kHz-re állította, hogy a mozgások pontosabban számíthatók legyenek. Andy általában túlzásba esik, és ha a gravitációt utánozzuk, akkor azt a lehető legpontosabban tesszük!

De mi van akkor, ha az időzítő gyorsulása valamilyen módon befolyásolja a program általános időzítését, és így a memóriakártya adatátviteli sebességét szabályozó órát?

Megjegyeztem az időzítő kódját. A hiba nem jelentkezett újra. De ez nem jelenti azt, hogy kijavítottuk, mert a hiba véletlenszerűen történt. Mi van, ha csak szerencsém van?

Néhány nappal később ismét kísérleteztem a tesztprogrammal. A hiba nem ismétlődött meg. Visszamentem a játék teljes kódbázisához, és megváltoztattam a mentési és betöltési kódot úgy, hogy a programozható időzítő visszaáll az eredeti értékre (100 Hz), mielőtt hozzáférnék a memóriakártyához, majd ismét vissza 1 kHz-re. Több baleset nem történt.

De miért történt ez?

Ismét visszatértem a tesztprogramhoz. 1 kHz-es időzítővel próbáltam valami mintát találni a hiba fellépésében. Végül észrevettem, hogy a hiba akkor jelentkezik, amikor valaki PS1 vezérlővel játszik. Mivel én magam ritkán csinálom ezt, miért van szükségem vezérlőre a mentési és betöltési kód tesztelésekor? - Nem vettem észre ezt a függőséget. Ám egy nap az egyik művészünk arra várt, hogy befejezzem a tesztelést - abban a pillanatban biztosan káromkodtam -, és idegesen csavarta a vezérlőt a kezében. Hiba történt. "Várj, mi?! Gyerünk, csináld újra!"

Amikor rájöttem, hogy ez a két esemény összefügg, könnyen reprodukálhattam a hibát: elkezdtem írni a memóriakártyára, elmozdítottam a vezérlőt, tönkretettem a memóriakártyát. Nekem hardverhibának tűnt.

Elmentem Connie-hoz, és elmondtam a felfedezésemet. Továbbította az információkat az egyik mérnöknek, aki a PS1-et tervezte. – Lehetetlen – válaszolta –, ez nem lehet hardverprobléma. Megkértem Connie-t, hogy szervezzen nekünk egy csevegést.

A mérnök felhívott, és vitatkoztunk vele az ő törött angolján és az én (rendkívül) törött japánomon. Végül azt mondtam: "Hadd küldjem el a 30 soros tesztprogramomat, ahol a vezérlő mozgása hibát okoz." Egyetértett. Azt mondta, hogy ez időpocsékolás volt, és rettenetesen elfoglalt egy új projekten, de feladná, mert nagyon fontos fejlesztők vagyunk a Sony számára. Kitisztítottam a tesztprogramomat, és elküldtem neki.

Másnap este (mi Los Angelesben voltunk, ő pedig Tokióban) felhívott, és zavartan bocsánatot kért. Hardveres probléma volt.

Nem tudom pontosan mi volt a hiba, de a Sony központjában hallottak szerint, ha elég magasra állítottad az időzítőt, akkor az alaplapon lévő komponenseket zavarta meg az időzítő kristály környékén. Az egyik a memóriakártya adatátviteli sebességének vezérlője volt, amely a vezérlők adatátviteli sebességét is beállította. Nem vagyok mérnök, szóval lehet, hogy össze vagyok zavarodva.

De a lényeg az, hogy az alaplapon lévő alkatrészek között interferencia volt. És amikor egyidejűleg adatokat továbbítottunk a vezérlőporton és a memóriakártya-porton keresztül egy 1 kHz-es időzítővel, bitek tűntek el, adatok elvesztek, és a kártya megsérült.

Hibás tehenek

Az 1980-as években a mentorom, Szergej szoftvert írt a CM-1800-hoz, a PDP-11 szovjet klónjához. Ezt a mikroszámítógépet nemrég telepítették a Szverdlovszk melletti vasútállomásra, amely a Szovjetunió fontos közlekedési csomópontja. Az új rendszert a kocsik és a teherforgalom irányítására tervezték. De kiderült, hogy ez egy bosszantó hiba, amely véletlenszerű összeomláshoz és összeomláshoz vezetett. Az esések mindig akkor következtek be, amikor valaki este hazament. De a másnapi alapos vizsgálat ellenére, minden manuális és automatikus teszttel a számítógép megfelelően működött. Ez általában faji állapotot vagy más, bizonyos feltételek mellett fellépő párhuzamossági hibát jelez. Szergej belefáradt a késő esti hívásokba, és úgy döntött, hogy az ügy végére jár, és mindenekelőtt megérti, milyen körülmények vezettek a rendezőpályaudvaron a számítógép meghibásodásához.

Először statisztikai adatokat gyűjtött az összes megmagyarázhatatlan esésről, és dátum és idő szerint ábrázolta őket. A minta nyilvánvaló volt. Néhány napos figyelés után Szergej rájött, hogy könnyen megjósolhatja a jövőbeli rendszerhibák idejét.

Hamar rájött, hogy a fennakadások csak akkor következtek be, amikor az állomás Észak-Ukrajnából és Nyugat-Oroszországból egy közeli vágóhídra tartó marhavagonokat válogatta ki. Ez már önmagában is furcsa volt, mert a vágóhidat sokkal közelebbi, kazahsztáni gazdaságok látták el.

A csernobili atomerőmű 1986-ban felrobbant, a radioaktív csapadék pedig lakhatatlanná tette a környező területeket. Észak-Ukrajnában, Fehéroroszországban és Nyugat-Oroszországban nagy területek szennyezettek. Az érkező autók magas sugárzási szintjére gyanakodva Szergej kidolgozott egy módszert ennek az elméletnek a tesztelésére. A lakosságnak megtiltották a doziméterek használatát, így Szergejt több katona leállította a vasútállomáson. Többszöri vodkázás után sikerült meggyőznie a katonát, hogy mérje meg a sugárzás mértékét az egyik gyanús autóban. Kiderült, hogy a szint sokszorosa a megszokott értékeknek.

A szarvasmarhák nemcsak sok sugárzást bocsátottak ki, de szintje olyan magas volt, hogy véletlenszerű bitvesztéshez vezetett az állomás melletti épületben található SM-1800 memóriájában.

A Szovjetunióban élelmiszerhiány volt, és a hatóságok úgy döntöttek, hogy a "csernobili" húst összekeverik az ország más régióiból származó hússal. Ez lehetővé tette a radioaktivitás általános szintjének csökkentését értékes erőforrások pazarlása nélkül. Szergej erről tudomást szerezve azonnal kitöltötte a kivándorlási dokumentumokat. A számítógép összeomlása pedig magától megszűnt, amikor a sugárzás szintje idővel csökkent.

A csöveken keresztül

Valamikor a Movietech Solutions szoftvereket készített a mozik számára, amelyeket könyvelésre, jegyértékesítésre és általános igazgatásra terveztek. A zászlóshajó alkalmazás DOS-os verziója igen népszerű volt a kis- és közepes méretű színházi láncok körében Észak-Amerikában. Így nem meglepő, hogy a legújabb érintőképernyőkkel és önkiszolgáló kioszkokkal integrált, mindenféle jelentéskészítő eszközzel felszerelt Windows 95-ös verzió bejelentésekor az is gyorsan népszerűvé vált. A frissítés legtöbbször zökkenőmentesen ment. A helyszíni informatikusok új hardvert telepítettek, adatokat migráltak, és az üzlet folytatódott. Kivéve amikor nem tartott. Amikor ez megtörtént, a cég elküldte Jamest, becenevén "The Cleaner".

Bár ez a becenév egy aljas típusra utal, a takarító azonban csak az oktató, a telepítő és a minden mesterségbeli jack kombinációja. James néhány napot az ügyfélnél töltött az összes komponens összerakásával, majd még néhány napot azzal, hogy megtanítsa a személyzetnek az új rendszer használatát, kijavítsa a felmerülő hardverproblémákat, és ténylegesen átsegítse a szoftvert a kialakuló éveiben.

Ezért nem meglepő, hogy ezekben a mozgalmas időkben James reggel megérkezett az irodába, és mielőtt az íróasztalához ért volna, a menedzser üdvözölte, és a szokásosnál nagyobb koffeinnel töltötte.

– Attól tartok, a lehető leghamarabb az újskóciai Annapolisba kell menned. Az egész rendszer leállt, és egy éjszakai munka után a mérnökeikkel nem tudjuk kideríteni, mi történt. Úgy tűnik, a hálózat meghibásodott a szerveren. De csak azután, hogy a rendszer néhány percig futott.

– Nem tértek vissza a régi rendszerhez? James egészen komolyan válaszolt, bár gondolataiban elkerekedett a szeme a meglepetéstől.

- Pontosan: az informatikusuk "prioritást váltott", és úgy döntött, a régi szerverükkel távozik. James, hat helyen telepítették a rendszert, és csak fizettek a prémium támogatásért, és üzletük most úgy működik, mint az 1950-es években.

James kissé felegyenesedett.

- Az már más kérdés. Oké, kezdjük.

Amikor megérkezett Annapolisba, az első dolga az volt, hogy megtalálja az ügyfél első moziját, ahol probléma volt. A repülőtéren készült térképen minden rendben volt, de a kívánt cím környéke gyanúsnak tűnt. Nem gettó, hanem film noirra emlékeztet. Amikor James leparkolt a járdaszegélynél, egy prostituált odament hozzá. Annapolis méretét tekintve valószínűleg ez volt az egyetlen az egész városban. Megjelenése azonnal a híres karakterre emlékeztette, aki pénzért kínált szexet a képernyőn. Nem, nem Julia Robertsről, hanem Jon Voightról [hivatkozás a "Midnight Cowboy" című filmre - kb. per.].

A prostituáltat hazaküldve James moziba ment. A környék jobb lett, de még mindig lepukkant benyomást keltett. Nem mintha James túlzottan aggódott volna. Volt már rossz helyeken. Ez pedig Kanada volt, ahol még a betörők is olyan udvariasak, hogy "köszönöm" a pénztárcájának elvétele után.

A mozi oldalsó bejárata egy nyirkos sikátorban volt. James az ajtóhoz lépett és bekopogott. Hamarosan csikorgott, és kissé kinyílt.

Takarító vagy? - hallatszott egy rekedtes hang belülről.

– Igen, én vagyok… azért jöttem, hogy helyrehozzam a dolgokat.

James bement a mozi előcsarnokába. Valószínűleg nem volt más választása, a személyzet papír jegyeket kezdett kiadni a látogatóknak. Ez megnehezítette a pénzügyi beszámolást, nem beszélve az érdekesebb részletekről. Ám az alkalmazottak megkönnyebbülten üdvözölték Jamest, és azonnal a szerverszobába vitték.

Első pillantásra minden rendben volt. James bejelentkezett a szerverre, és ellenőrizte a szokásos gyanús helyeket. Nincs mit. James azonban elővigyázatosságból leállította a szervert, kicserélte a hálózati kártyát, és visszaállította a rendszert. Azonnal teljes bevételt szerzett. A személyzet ismét jegyárusításba kezdett.

James felhívta Markot, és tájékoztatta a helyzetről. Nem nehéz elképzelni, hogy James esetleg itt szeretne elidőzni, és megnézni, történik-e valami váratlan. Lement a lépcsőn, és faggatni kezdte a személyzetet és a történteket. Nyilvánvalóan leállt a rendszer. Ki-be kapcsolták, minden működött. De 10 perc múlva a rendszer leállt.

Éppen abban a pillanatban történt valami hasonló. Egyszer csak a jegyrendszer elkezdett hibákat dobni. A személyzet felsóhajtott, és felkapta a papírjegyeket, miközben James a szerverterembe sietett. Minden rendben volt a szerverrel.

Ekkor bejött az egyik alkalmazott.

A rendszer újra működik.

James értetlenül állt, mert nem tett semmit. Pontosabban semmi, amitől működne a rendszer. Kijelentkezett, felvette a telefont, és felhívta a cége help deskjét. Hamarosan ugyanaz az alkalmazott lépett be a szerverszobába.

- A rendszer leállt.

James a szerverre pillantott. Többszínű formák érdekes és ismerős mintája táncolt a képernyőn - kaotikusan csavarva és összefonódó csöveket. Mindannyian láttuk ezt a képernyővédőt valamikor. Gyönyörűen volt visszaadva és szó szerint hipnotizált.


James megnyomta a gombot, és a minta eltűnt. A jegypénztárhoz sietett, és útközben találkozott egy hozzá visszatérő alkalmazottal.

A rendszer újra működik.

Ha képes mentálisan egy facepalm-ot készíteni, akkor James pontosan ezt tette. Képernyőkímélő. OpenGL-t használ. Ezért működés közben a szerver processzorának összes erőforrását felhasználja. Ennek eredményeként a szerver minden hívása időtúllépéssel ér véget.

James visszament a szerverszobába, bejelentkezett, és a gyönyörű pipes képernyővédőt egy üres képernyőre cserélte. Vagyis a processzor erőforrásainak 100%-át fogyasztó képernyővédő helyett egy másikat telepítettem, ami nem fogyaszt erőforrást. Aztán vártam 10 percet, hogy ellenőrizzem a sejtésemet.

Amikor James megérkezett a következő moziba, azon gondolkodott, hogyan magyarázza el menedzserének, hogy éppen 800 mérföldet repült, hogy kikapcsolja a képernyővédőt.

Hiba a hold egy bizonyos fázisában

Igaz sztori. Egyszer volt egy szoftverhiba, ami a holdfázistól függött. Volt egy kis szubrutin, amelyet gyakran használtak különféle MIT-programokban a Hold valódi fázisának közelítésének kiszámítására. A GLS ezt az alprogramot egy LISP programba építette be, amely egy fájl írásakor egy majdnem 80 karakter hosszú időbélyegző karakterláncot ad ki. Nagyon ritkán az üzenet első sora túl hosszú volt, és a következő sorba került. És amikor a program elolvasta ezt a fájlt, átkozott. Az első sor hossza a pontos dátumtól és időponttól, valamint a fázisspecifikáció hosszától függött az időbélyegző nyomtatásának időpontjában. Vagyis a hiba szó szerint a holdfázistól függött!

Első papírkiadás Szakzsargon fájl (Steele-1983) tartalmazott egy mintát egy ilyen sorból, amely a leírt hibát eredményezte, de a készítő "javította" azt. Ezt azóta "holdfázis-hibának" nevezik.

Legyen azonban óvatos a feltételezésekkel. Néhány évvel ezelőtt a CERN (Európai Nukleáris Kutatási Központ) mérnökei hibákba ütköztek a Nagy Elektron-Pozitronütköztetőben végzett kísérleteik során. Mivel a számítógépek aktívan feldolgozzák az eszköz által generált óriási mennyiségű adatot, mielőtt megmutatnák az eredményt a tudósoknak, sokan azt feltételezték, hogy a szoftver valamilyen módon érzékeny a holdfázisra. Néhány kétségbeesett mérnök rájött az igazság mélyére. A hiba a 27 km hosszú gyűrű geometriájának enyhe változása miatt keletkezett, a Föld deformációja miatt a Hold áthaladása során! Ez a történet „Newton bosszúja a részecskefizikán” néven került be a fizikusok folklórjába, és a legegyszerűbb és legrégebbi fizikai törvények és a legfejlettebb tudományos fogalmak összekapcsolásának példája.

A WC lehúzása megállítja a vonatot

A legjobb hardverhiba, amiről hallottam, egy franciaországi nagysebességű vonaton volt. A hiba a vonat vészfékezéséhez vezetett, de csak akkor, ha utasok voltak a fedélzeten. Minden ilyen esetben a vonatot kivonták a forgalomból, ellenőrizték, de nem találtak semmit. Aztán ismét sorra küldték, és azonnal leállt.

Az egyik ellenőrzés során a vonat egyik mérnöke a WC-re ment. Hamar elmosta, BUMM! Vészmegálló.

A mérnök felvette a kapcsolatot a sofőrrel, és megkérdezte:

- Mit csináltál közvetlenül fékezés előtt?

- Hát lelassítottam az ereszkedésnél...

Furcsa volt, mert normál menet közben a vonat több tucatszor lelassul az ereszkedéseken. A vonat továbbment, és a következő ereszkedésnél a sofőr figyelmeztetett:

- Lassítani fogok.

Nem történt semmi.

– Mit csináltál az utolsó fékezéskor? - kérdezte a sofőr.

– Hát… a wc-n voltam…

- Na, akkor menj ki a wc-re, és tedd azt, amit, amikor megint lementünk!

A mérnök kiment a vécére, és amikor a sofőr figyelmeztetett: "Fékek", leöblítette a vizet. Természetesen a vonat azonnal megállt.

Most reprodukálhatták a problémát, és meg kellett találniuk az okot.

Két perccel később észrevették, hogy a motorfékező távirányító kábele (a vonat mindkét végén egy motor volt) le van választva az elektromos szekrény faláról, és azon a relén fekszik, amely a WC-dugó mágnesszelepét vezérli ... Amikor a relé bekapcsolva, zavarta a fékkábelt, és a rendszer üzembiztos egyszerűen bekapcsolta a vészfékezést.

Átjáró, amely utálta a FORTRAN-t

Néhány hónappal ezelőtt észrevettük, hogy a hálózati kapcsolatok a szárazföldi hálózathoz [ez Hawaii-on történt] nagyon-nagyon lelassulnak. 10-15 percig tarthat, majd hirtelen újra megjelenik. Nem sokkal később kollégám panaszkodott nekem, hogy hálózati kapcsolatok vannak a szárazföldön általában nem működik. Volt valami FORTRAN kódja, amit át kellett másolni egy szárazföldi gépre, de az nem működött, mert "a hálózat nem tartott elég sokáig ahhoz, hogy az FTP letöltése befejeződjön".

Igen, kiderült, hogy hálózati meghibásodások történtek, amikor egy kolléga megpróbált FTP-vel küldeni egy FORTRAN forráskód fájlt egy szárazföldi gépre. Megpróbáltuk archiválni a fájlt: aztán csendben átmásolták (de a célgépen nem volt kicsomagoló, így nem oldódott meg a probléma). Végül a FORTRAN kódot nagyon apró darabokra "bontottuk" és egyenként elküldtük. A töredékek nagy részét probléma nélkül másolták, de néhány darab nem ment át, vagy utána ment számos próbálkozások.

A problémás töredékek vizsgálata után megállapítottuk, hogy van valami közös bennük: mindegyikben vannak olyan megjegyzésblokkok, amelyek nagy C betűből álló sorokkal kezdődnek és végződnek (kollégaként inkább a FORTRAN-t kommentálta). E-maileket küldtünk az anyaországi hálózati szakembereknek, és segítséget kértünk. Természetesen olyan fájlmintákat akartak látni, amelyeket nem lehet FTP-n keresztül továbbítani... de a leveleink nem jutottak el hozzájuk. Végül kitaláltunk egy egyszerűt leírnihogy néznek ki az át nem küldött fájlok. Sikerült :) [Merjek ide egy példát az egyik problémás FORTRAN megjegyzésre? Valószínűleg nem éri meg!]

Végül sikerült rájönnünk. A közelmúltban új átjárót építettek ki a mi kampuszrészünk és az anyaország hálózati csatlakozása közé. ÓRIÁSI gondjai voltak az ismétlődő nagy C-töredékeket tartalmazó csomagok továbbításával! Csak néhány ilyen csomag tudta felvenni az átjáró összes erőforrását, és nem tette lehetővé a legtöbb csomag áttörését. Panaszkodtunk az átjáró gyártójának... és azt válaszolták: „Ah, igen, találkoztál egy hibával a többszöri C-vel! Már tudunk róla." Végül úgy oldottuk meg a problémát, hogy új átjárót vásároltunk egy másik gyártótól (az előbbi védelmében egyesek számára előnyt jelenthet a FORTRAN programok átvitelének képtelensége!).

Nehéz idők

Néhány évvel ezelőtt, miközben egy Perl ETL rendszeren dolgoztam, amelyet a 40. fázisú klinikai vizsgálatok költségeinek csökkentésére terveztek, körülbelül 000 1 dátumot kellett feldolgoznom. Közülük ketten nem mentek át a vizsgán. Ez nem nagyon zavart, mert ezek a dátumok az ügyfél által megadott adatokból származtak, ami sokszor mondjuk meglepő volt. De az eredeti adatok ellenőrzésekor kiderült, hogy ezek a dátumok 2011. január 1. és 2007. január 30. Azt hittem, hogy a hiba az imént írt programban van, de kiderült, hogy már XNUMX éves. Ez titokzatosan hangozhat azok számára, akik nem ismerik a szoftveres ökoszisztémát. Egy másik cég régóta tartó pénzkereseti döntése miatt az ügyfelem fizetett, hogy javítsam ki azt a hibát, amelyet az egyik cég véletlenül, a másik pedig szándékosan vezetett be. Ahhoz, hogy megértsd, miről beszélek, beszélnem kell a cégről, amely hozzáadta az ennek következtében hibássá vált funkciót, valamint néhány további érdekes eseményt, amelyek hozzájárultak az általam javított rejtélyes hibához.

A régi szép időkben az Apple számítógépei néha spontán módon visszaállították a dátumot 1. január 1904-re. Az ok egyszerű volt: elemes "rendszerórát" használtak a dátum és az idő nyomon követésére. Mi történt, amikor lemerült az akkumulátor? A számítógépek a korszak óta eltelt másodpercek számával kezdték nyomon követni a dátumot. A korszak volt a referencia dátum, a Macintosh esetében pedig 1. január 1904. És miután az akkumulátor lemerült, az aktuális dátumot visszaállították a megadottra. De miért történt ez?

Korábban az Apple 32 bitet használt az eredeti dátum óta eltelt másodpercek számának tárolására. Egy bit két érték egyikét tárolhatja - 1 vagy 0. Két bit négy érték egyikét tárolhatja: 00, 01, 10, 11. Három bit - a nyolc érték egyike: 000, 001, 010, 011, 100, 101, 110, 111 stb. A 32 pedig 232 érték egyikét, azaz 4 294 967 296 másodpercet tárolhat. Az Apple dátumainál ez körülbelül 136 év volt, tehát a régebbi Mac-ek nem tudják kezelni a 2040 utáni dátumokat. És ha a rendszer akkumulátora lemerül, a dátum visszaáll 0 másodpercre a korszak óta, és manuálisan kell beállítania a dátumot minden alkalommal, amikor bekapcsolja a számítógépet (vagy amíg új elemet nem vásárol).

Azonban az Apple döntése, hogy a dátumokat a korszak óta eltelt másodpercekként tárolja, azt jelentette, hogy nem tudtuk kezelni a korszak előtti dátumokat, aminek messzemenő következményei voltak, mint látni fogjuk. Az Apple egy funkciót mutatott be, nem egy hibát. Ez többek között azt jelentette, hogy a Macintosh operációs rendszer immunis volt a „millennium bug”-ra (ami nem mondható el sok olyan Mac-alkalmazásról, amely saját dátumrendszerrel rendelkezett a korlátozások megkerülésére).

Menj tovább. A Lotus 1-2-3-at, az IBM gyilkos alkalmazását használtuk, amely segített elindítani a PC-forradalmat, bár az Apple számítógépeken volt VisiCalc, ami sikeressé tette a személyi számítógépeket. Az igazat megvallva, ha az 1-2-3 nem jelent meg, a PC-k nem szálltak volna fel, és a személyi számítógép története egészen másképp alakulhatott volna. A Lotus 1-2-3 helytelenül szökőévként kezelte az 1900-as évet. Amikor a Microsoft kiadta első táblázatát, a Multiplant, kis részesedést szerzett a piacból. És amikor az Excel projekt elindult, úgy döntöttek, hogy nemcsak a sor- és oszlopelnevezési sémát másolják a Lotus 1-2-3-ból, hanem a hibákkal való kompatibilitást is biztosítják azáltal, hogy az 1900-at szándékosan szökőévként kezelik. Ez a probléma a mai napig fennáll. Vagyis az 1-2-3-ban hiba volt, de az Excelben tudatos döntés volt, ami biztosította, hogy az 1-2-3 minden felhasználója az adatok megváltoztatása nélkül importálja a táblázatait az Excelbe, még akkor is, ha azok hibásak voltak.

De volt itt egy másik probléma is. A Microsoft először kiadta az Excelt Macintoshra, amely nem ismerte fel az 1. január 1904-je előtti dátumokat. Az Excelben a korszak kezdete 1. január 1900. volt. Ezért a fejlesztők olyan változtatást hajtottak végre, hogy programjuk felismeri a korszak típusát, és a kívánt korszaknak megfelelően tárolja magában az adatokat. A Microsoft még egy magyarázó cikket is írt róla. És ez a megoldás a hibámhoz vezetett.

Az ETL-rendszerem olyan Excel-táblázatokat kapott a vásárlóktól, amelyek Windows-on készültek, de Mac-en is létrehozhatók. Ezért a táblázatban szereplő korszak kezdete vagy 1. január 1900. vagy 1. január 1904. lehet. Hogyan lehet megtudni? Az Excel fájlformátum megjeleníti a szükséges információkat, de az általam használt elemző nem (most már igen), és feltételezi, hogy ismeri egy adott tábla korszakát. Valószínűleg több időt is tölthettem volna azzal, hogy kitaláljam az Excel binárisát, és elküldjem a javítást az elemző szerzőjének, de sok más dolgom is volt az ügyfélért, ezért gyorsan írtam egy heurisztikát a korszak meghatározásához. Egyszerű volt.

Az Excelben az 5. július 1998-i dátum a következő formátumban jeleníthető meg: „07-05-98” (haszontalan amerikai rendszer), „5. július 98.”, „5. július 1998.”, „5. július 98.”, vagy valami más haszontalan formátum (ironikus módon az egyik formátum, amelyet az Excel verzióm nem kínált, az ISO 8601 szabvány volt). A táblázatban azonban a nyers dátumot vagy „35981”-ként az 1900-as epocha, vagy „34519”-ként az 1904-es epocha esetében tároltuk (a számok a korszak óta eltelt napok számát jelentik). Egy egyszerű elemzővel kinyertem az évet a formázott dátumból, majd az Excel elemzővel az évet a formázatlan dátumból. Ha mindkét érték 4 évvel eltért, tudtam, hogy epoch-1904 rendszert használok.

Miért nem csak formázott dátumokat használtam? Mert 5. július 1998-ét úgy lehet formázni, hogy "98. július", a hónap napja hiányzik. Olyan sok cégtől kaptunk táblázatokat, amelyek olyan különböző módon készítették el azokat, hogy rajtunk (jelen esetben rajtam) múlott, hogy kitaláljuk a dátumokat. Ráadásul, ha az Excelnek sikerül, akkor nekünk is kell!

Aztán belefutottam a 39082-be. Hadd emlékeztessem önöket, hogy a Lotus 1-2-3 az 1900. szökőévnek számított, és ez az Excelben is hűen megismétlődött. És mivel ez egy napot adott 1900-hoz, sok dátumfüggvény hibás lehet ezen a napon. Tehát a 39082 lehet 1. január 2011-je (Mac-en) vagy 31. december 2006-e (Windows-on). Ha az „évelemzőm” a formázott értékből kivette a 2011-es évet, akkor minden rendben van. De mivel az Excel elemző nem tudja, hogy melyik korszakot használja, alapértelmezés szerint az epoch-1900, és a 2006-os évet adja vissza. Az alkalmazásom látta, hogy 5 év a különbség, hibaként kezelte, naplózta, és formázatlan értéket adott vissza.

Hogy ezt megkerüljem, ezt írtam (pszeudokód):

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

És akkor mind a 40 000 dátumot helyesen elemezte.

Nagy nyomtatási munkák közepette

Az 1980-as évek elején apám a Storage Technology-nál dolgozott, egy már megszűnt részlegnél, amely szalagos meghajtókat és pneumatikus rendszereket készített nagy sebességű szalagadagoláshoz.

Újratervezték a meghajtókat úgy, hogy egy központi „A” meghajtót hét „B” meghajtóhoz csatlakoztassanak, és az „A” meghajtót vezérlő kis OS RAM-ban az olvasási és írási műveleteket az összes „B” meghajtóra delegálhassa.

Minden alkalommal, amikor az A meghajtót elindították, egy hajlékonylemezt kellett behelyezni az A-hoz csatlakoztatott periféria meghajtóba, hogy az operációs rendszer betölthető legyen a memóriájába. Rendkívül primitív volt: a számítási teljesítményt egy 8 bites mikrokontroller biztosította.

Ennek a berendezésnek a célközönsége a nagyon nagy adattárral rendelkező cégek – bankok, kereskedelmi láncok stb. – voltak, akiknek sok címcímkét vagy bankszámlakivonatot kellett nyomtatniuk.

Egy ügyfélnek problémája volt. Egy nyomtatási feladat közepén egy bizonyos "A" meghajtó leáll, ami az egész feladat leállását okozza. A meghajtó visszaállításához a személyzetnek mindent újra kellett indítania. És ha ez egy hatórás feladat kellős közepén történt, akkor rengeteg drága számítógépes idő veszett el, és az egész művelet ütemezése felborult.

A Storage Technologies technikusait küldték. De minden erőfeszítésük ellenére nem tudták reprodukálni a hibát a tesztkörülmények között: úgy tűnt, hogy nagy nyomtatási munkák közepette fordul elő. A probléma nem a hardverrel volt, mindent kicseréltek, amit lehetett: RAM-ot, mikrokontrollert, hajlékonylemez-meghajtót, a szalagos meghajtó minden elképzelhető részét - a probléma továbbra is fennáll.

Aztán a technikusok felhívták a főhadiszállást és felhívták a Szakértőt.

A szakértő fogott egy széket és egy csésze kávét, leült a számítástechnikai teremben – akkoriban ott voltak a számítógépek számára fenntartott szobák –, és nézte, ahogy a személyzet sorba állít egy nagy nyomtatási munkát. A szakértő megvárta a kudarc bekövetkezését, és meg is történt. Mindenki a Szakértőre nézett – és fogalma sem volt, miért történt ez. Így elrendelte, hogy a munkát helyezzék vissza a sorba, és az összes személyzet és technikus visszament dolgozni.

A szakértő hátradőlt a székében, és várta a kudarcot. Körülbelül hat óra telt el, és a hiba bekövetkezett. A Szakértő megint kifogyott az ötletekből, eltekintve attól, hogy minden egy zsúfolt szobában történt. Elrendelte a feladat újraindítását, újra leült és várt.

A harmadik kudarcnál a Szakértő észrevett valamit. A hiba akkor következett be, amikor a személyzet egy idegen meghajtóban szalagot cserélt. Sőt, a hiba akkor következett be, amikor az egyik alkalmazott áthaladt egy bizonyos csempén a padlón.

Az emelt padló 6-8 hüvelyk magasságban lerakott alumínium csempéből készült. Számítógépekből származó vezetékek futottak az emelt padló alatt, hogy valaki véletlenül se lépjen rá egy fontos kábelre. A csempéket nagyon szorosan lerakták, hogy a törmelék ne kerüljön az emelt padlóra.

A szakértő rájött, hogy az egyik csempe deformálódott. Amikor egy alkalmazott a sarkára lépett, a csempe a széleit a szomszédos csempékhez súrolta. A csempéket összekötő műanyag alkatrészek is dörzsölődtek velük, ami rádiófrekvenciás interferenciát okozó statikus mikrokisüléseket okozott.

Ma a RAM sokkal jobban védett a rádiófrekvenciás interferencia ellen. De azokban az években ez nem így volt. A szakember rájött, hogy ezek az interferenciák megzavarták a memóriát, és ezzel együtt az operációs rendszer működését is. Felhívta az ügyfélszolgálatot, új csempét rendelt, saját maga szerelte fel, és a probléma megszűnt.

Ez a dagály!

A történet egy szerverszobában játszódik, egy portsmouthi iroda negyedik vagy ötödik emeletén (szerintem), a dokk területén.

Egy nap a Unix szerver a fő adatbázissal összeomlott. Újraindították, de boldogan zuhant tovább újra és újra. Úgy döntöttünk, felhívunk valakit a támogatási szolgálattól.

Támogatás haver... Azt hiszem, Marknak hívták, de ez nem fontos... Azt hiszem, nem ismerem. Nem számít, tényleg. Maradjunk Marknál, jó? Nagy.

Így aztán néhány órával később megérkezett Mark (leedstől Portsmouthig nem sok az út, ugye), bekapcsolta a szervert, és minden probléma nélkül működött. Tipikus kibaszott támogatás, az ügyfél emiatt nagyon ideges lesz. Mark átnézi a naplófájlokat, és nem talál semmi különöset. Aztán Mark visszaszáll a vonatra (vagy akármilyen közlekedési eszközzel is jött, sánta tehén lehetett, amennyire én tudom… nos, mindegy, oké?), és visszamegy Leedsbe. nap.

Még aznap este a szerver újra összeomlik. A történet ugyanaz... a szerver nem emelkedik. Mark megpróbál távolról segíteni, de az ügyfél nem tudja elindítani a szervert.

Még egy vonat, busz, citromos habcsók vagy más baromság, és Mark ismét Portsmouthban van. Nézd, a szerver problémamentesen töltődik be! Csoda. Mark több órán keresztül ellenőrzi, hogy minden rendben van-e az operációs rendszerrel vagy a szoftverrel, és Leedsbe megy.

A nap közepe táján a szerver összeomlik (nyugodj meg!). Ezúttal ésszerűnek tűnik, hogy a hardvertámogató embereket cseréljék ki a szerverre. De nem, kb 10 óra után az is esik.

A helyzet több napig ismétlődött. A szerver működik, körülbelül 10 óra múlva összeomlik, és a következő 2 órában nem indul el. Megnézték a hűtést, a memóriaszivárgást, mindent megnéztek, de nem találtak semmit. Aztán a karambolok abbamaradtak.

Gondtalanul telt el a hét... mindenki boldog volt. Boldog, amíg minden el nem kezdődik. A kép ugyanaz. 10 óra munka, 2-3 óra állásidő...

És akkor valaki (azt hiszem, azt mondták nekem, hogy ennek az embernek semmi köze az informatikához) azt mondta:

– Ez a dagály!

A felkiáltást üres pillantások fogadták, és valószínűleg valakinek a keze habozott a gombnál, hogy hívja-e az őrt.

– Nem működik az árral.

Ez teljesen idegen fogalomnak tűnik az IT-támogató dolgozók számára, akik valószínűleg nem olvassák a Tide Yearbookot, miközben leülnek kávézni. Kifejtették, hogy ez semmiképpen nem hozható összefüggésbe az árral, mert a szerver egy hete működött hiba nélkül.

"A múlt héten alacsony volt az apály, de ezen a héten magas az apály."

Egy kis terminológia azoknak, akiknek nincs jogosítványuk jachtvitorlázásra. Az árapály a holdciklustól függ. És ahogy a Föld forog, 12,5 óránként a Nap és a Hold gravitációs vonzása árhullámot hoz létre. A 12,5 órás ciklus elején dagály, a ciklus közepén apály, majd a végén ismét dagály következik be. De ahogy változik a Hold pályája, úgy változik az apály és a dagály közötti különbség is. Amikor a Hold a Nap és a Föld között, vagy a Föld ellenkező oldalán van (telihold vagy a Hold hiánya), akkor a Syzygy-apályt kapjuk - a legmagasabb és a legalacsonyabb apályt. A félholdnál négyzetes dagályokat kapunk - a legalacsonyabb dagályokat. A két véglet közötti különbség jelentősen csökken. A holdciklus 28 napig tart: syzygy - kvadratúra - syzygy - kvadratúra.

Amikor a technikusoknak elmagyarázták az árapály-erők lényegét, azonnal arra gondoltak, hogy ki kell hívniuk a rendőrséget. És teljesen logikus. De kiderült, hogy a csávónak igaza volt. Két héttel korábban egy romboló kötött ki az iroda közelében. Valahányszor az árapály egy bizonyos magasságba emelte, a hajó radaroszlopa a szerverterem padlójának szintjén kötött ki. A radar (vagy elektronikus harci felszerelés, vagy más katonai játékszer) pedig káoszt teremtett a számítógépekben.

Repülési küldetés egy rakéta számára

Azt a feladatot kaptam, hogy egy nagy (körülbelül 400 2.5.1 soros) rakétakilövő parancsnoki és vezérlőrendszert portoljak át az operációs rendszer, a fordító és a nyelv új verzióira. Pontosabban a Solaris 7-től a Solaris 83-ig, és az Ada 95-ban írt Verdix Ada Development System-től (VADS) az Ada XNUMX-ben írt Rational Apex Ada-ig. A VADS-t a Rational megvásárolta, és a terméke elavult, pedig a Rational megpróbálta A VADS-specifikus csomagok kompatibilis verzióinak megvalósítása az Apex fordítóprogramra való átállás megkönnyítése érdekében.

Három ember segített abban, hogy tisztán lefordítsam a kódot. Két hétig tartott. Aztán egyedül dolgoztam, hogy működjön a rendszer. Röviden, ez volt a szoftverrendszer legrosszabb architektúrája és megvalósítása, amivel találkoztam, így további két hónapba telt a port befejezése. Ezután a rendszert tesztelésre bocsátották, ami még több hónapig tartott. A tesztelés során talált hibákat azonnal kijavítottam, de gyorsan lecsökkent a számuk (a forráskód egy éles rendszer volt, így a funkcionalitása elég megbízhatóan működött, csak az új fordítóhoz való adaptáció során felmerült hibákat kellett eltüntetni). Végül, amikor minden úgy működött, ahogy kell, átkerültem egy másik projektbe.

És a hálaadás előtti pénteken megcsörrent a telefon.

Körülbelül három héttel később a rakétakilövést kellett tesztelni, és a visszaszámláló laboratóriumi tesztek során a parancssort blokkolták. A való életben ez a tesztek megszakadásához vezetne, és ha a motor beindítása után néhány másodpercen belül dugulás lépne fel, akkor több visszafordíthatatlan művelet történne a segédrendszerekben, amelyek miatt hosszú - és költséges - hogy újra előkészítsem a rakétát. Nem indulna el, de sokan nagyon kiakadnának az időveszteség és a nagyon-nagyon nagy pénz miatt. Ne mondja senki, hogy a védelmi minisztérium szerénytelenül pénzt költ – még soha nem találkoztam olyan szerződéses menedzserrel, aki ne a költségvetést helyezte volna előtérbe vagy második helyre, majd az ütemezést.

Az előző hónapokban ezt a visszaszámlálási tesztet több százszor lefuttatták számos változatban, csak néhány kisebb akadozással. Tehát ennek a valószínűsége nagyon kicsi volt, de a következményei igen jelentősek. Szorozzuk meg mindkét tényezőt, és rájössz, hogy a hírek egy tönkrement ünnepi hetet jósoltak nekem és több tucat mérnöknek és menedzsernek.

És felfigyeltek rám, mint a rendszer áthelyezésére.

A legtöbb biztonsági szempontból kritikus rendszerhez hasonlóan sok paramétert naplóztak, így meglehetősen könnyű volt azonosítani azt a néhány sornyi kódot, amelyeket a rendszer összeomlása előtt végrehajtottak. És persze semmi szokatlan nem volt bennük, ugyanazokat a kifejezéseket szó szerint több ezerszer sikeresen végrehajtották ugyanazon futás során.

Az Apex-től a Rational-ig hívtuk az embereket, mert ők fejlesztették a fordítót, és az általuk fejlesztett szubrutinok egy részét gyanús kódban hívták meg. Nekik (és mindenki másnak is) az volt a benyomása, hogy egy szó szerint nemzeti jelentőségű probléma okát kell kideríteni.

Mivel semmi érdekes nem volt a naplókban, úgy döntöttünk, hogy megpróbáljuk reprodukálni a problémát egy helyi laboratóriumban. Ez nem volt könnyű feladat, hiszen az esemény 1000 futásból körülbelül egyszer fordult elő. Az egyik javasolt ok az volt, hogy a gyártó által fejlesztett mutex függvény meghívása (a VADS migrációs csomag része) Unlock nem oldotta fel. A függvényt meghívó feldolgozási szál a névlegesen másodpercenként érkezett szívverésüzeneteket dolgozta fel. Felemeltük a frekvenciát 10 Hz-re, azaz másodpercenként 10-szeresre, és elindítottuk a futást. Körülbelül egy óra múlva a rendszer leállt. A naplóban azt láttuk, hogy a rögzített üzenetek sorrendje ugyanaz, mint a törésteszt során. Csináltunk még pár menetet, rajt után 45-90 perccel stabilan blokkolt a rendszer, és minden alkalommal ugyanaz a pálya volt a napló. Annak ellenére, hogy technikailag most más kódot futtattunk – az üzenetek sebessége más volt –, a rendszer viselkedése azonos volt, így biztosak voltunk abban, hogy ez a betöltési forgatókönyv ugyanazt a problémát okozza.

Most azt kellett kideríteni, hogy a kifejezések sorozatában pontosan hol történt a blokkolás.

A rendszer ezen megvalósítása az Ada feladatrendszert használta, és elképesztően rosszul volt használva. A Tasks egy magas szintű, párhuzamosan futó konstrukció az Adában, amolyan végrehajtási szálak, amelyek csak magába a nyelvbe vannak beépítve. Amikor két feladatnak kommunikálnia kell, „találkozik”, kicseréli a szükséges adatokat, majd leállítja a randevúzást, és visszatér a független végrehajtáshoz. A rendszert azonban másként valósították meg. A célpont találkozása után a cél egy másik feladattal találkozott, amely aztán egy harmadikkal találkozott, és így tovább, amíg a feldolgozás be nem fejeződött. Ezt követően ezek a találkozások véget értek, és minden feladatnak vissza kellett térnie a végrehajtásához. Vagyis a világ legdrágább függvényhívási rendszerével volt dolgunk, amely a bemeneti adatok egy részének feldolgozása közben leállította a teljes "multitasking" folyamatot. És korábban ez nem okozott problémákat csak azért, mert az áteresztőképesség nagyon alacsony volt.

Azért írtam le ezt a feladatmechanizmust, mert amikor egy találkozót kértek vagy várhatóan befejeződik, előfordulhat "feladatváltás". Vagyis a processzor elkezdhet feldolgozni egy másik, végrehajtásra kész feladatot. Kiderült, hogy amikor egy feladat készen áll a találkozásra egy másik feladattal, egy teljesen más feladat végrehajtása indulhat el, és végül az irányítás visszatér az első találkozáshoz. És lehetnek más események is, amelyek feladatváltáshoz vezetnek; az egyik ilyen esemény egy rendszerfunkció hívása, például egy mutex nyomtatása vagy végrehajtása.

Ahhoz, hogy megértsem, melyik kódsor okozza a problémát, meg kellett találnom a módot egy kifejezéssorozat előrehaladásának rögzítésére anélkül, hogy a feladatkapcsolót elindítanám, ami megakadályozhatja az összeomlást. Szóval nem tudtam kihasználni Put_Line()hogy ne tegyen I/O-t. Beállíthatnék egy számláló változót vagy valami hasonlót, de hogyan látom az értékét, ha nem tudom megjeleníteni a képernyőn?

Ezenkívül a napló tanulmányozása során kiderült, hogy a szívverés üzenetek feldolgozásának leállása ellenére, amely blokkolta a folyamat összes I / O műveletét, és nem tette lehetővé más feldolgozás végrehajtását, más független feladatok végrehajtása folytatódott. Vagyis a munka nem volt teljesen blokkolva, csak a feladatok (kritikus) láncolata.

Ez volt a kulcs a blokkoló kifejezés kiértékeléséhez.

Készítettem egy Ada-csomagot, amely tartalmazott egy feladatot, egy felsorolt ​​típust és egy ilyen típusú globális változót. A felsorolt ​​literálokat a problémás szekvencia meghatározott kifejezéseihez kötötték (pl. Incrementing_Buffer_Index, Locking_Mutex, Mutex_Unlocked), majd olyan hozzárendelési kifejezéseket szúrt be, amelyek a megfelelő felsorolást a globális változóhoz rendelték. Mivel az objektumkód mindehhez egyszerűen állandót tartott a memóriában, rendkívül valószínűtlen volt egy feladatváltás a végrehajtása következtében. Először olyan kifejezésekre gyanakodtunk, amelyek képesek váltani a feladatokat, mivel a blokkolás végrehajtáskor történt, nem pedig visszatéréskor, amikor a feladatot visszakapcsolták (több okból is).

A követési feladat egyszerűen egy ciklusban futott, és időszakonként ellenőrizte, hogy megváltozott-e a globális változó értéke. Minden változtatásnál az érték egy fájlba került. Aztán rövid várakozás és új csekk. A változót azért írtam egy fájlba, mert a feladat csak akkor futott le, amikor a rendszer kiválasztotta azt végrehajtásra a feladatváltás során a problématerületen. Bármi is történik ebben a feladatban, nem érinti a többi nem kapcsolódó blokkolt feladatot.

Várható volt, hogy amikor a rendszer eléri a problémás kód végrehajtását, a globális változó minden következő kifejezésre való áttéréskor visszaáll. Ekkor történik valami, ami feladatváltást okoz, és mivel ennek végrehajtási frekvenciája (10 Hz) kisebb, mint a felügyeleti feladaté, a monitor rögzítheti és kiírhatja a globális változó értékét. Normál helyzetben enumok egy részhalmazának ismétlődő sorozatát kaphatom: egy változó utolsó értékeit a feladatváltáskor. Lebegtetéskor a globális változó már nem változhat, és az utoljára írt érték jelzi, hogy melyik kifejezés nem fejezte be a végrehajtást.

Futtassa a kódot követéssel. Lelógott. A megfigyelés pedig óraműként működött.

A napló a várt szekvenciát mutatta, amit a mutex meghívását jelző érték szakított meg Unlock, és a feladat nem fejeződött be – ahogy az a több ezer korábbi hívás esetében.

Az Apex mérnökei akkoriban kétségbeesetten elemezték a kódjukat, és megtalálták azt a helyet a mutexben, ahol elméletileg zárolás léphet fel. Ennek valószínűsége azonban nagyon kicsi volt, mivel csak egy bizonyos eseménysorozat, amely egy bizonyos időpontban bekövetkezik, vezethet blokkoláshoz. Murphy törvénye, emberek, ez Murphy törvénye.

A szükséges kódrészlet védelme érdekében lecseréltem a mutex függvényhívásokat (amelyek az operációs rendszer mutex funkcióira épültek) egy kis Ada natív mutex csomaggal, hogy szabályozzam a mutex hozzáférést az adott részhez.

Beillesztette a kódba, és lefuttatta a tesztet. Hét órával később a kód még mindig működött.

A kódomat elvitték a Rationalba, ahol lefordították, szétszedték, és ellenőrizték, hogy nem ugyanazt a megközelítést használja-e, mint a problémás mutex függvényeknél.

Pályafutásom legzsúfoltabb kódfelmérése volt 🙂 Körülbelül tíz mérnök és menedzser volt velem a teremben, még egy tucat ember csatlakozott konferenciahíváson keresztül – és mindannyian körülbelül 20 kódsort vizsgáltak meg.

A kódot tesztelték, új végrehajtható fájlokat fordítottak le és benyújtották formális regressziós tesztelésre. Néhány héttel később a visszaszámlálási tesztek sikeresek voltak, és a rakéta felszállt.

Oké, ez mind szép és jó, de mi értelme a történetnek?

Teljesen undorító probléma volt. Több százezer sornyi kód, párhuzamos végrehajtás, több mint egy tucat kölcsönhatásban lévő folyamat, rossz architektúra és rossz implementáció, interfészek a beágyazott rendszerekhez és több millió dollár elpazarlása. Nincs nyomás, ugye.

Nem én voltam az egyetlen, aki ezen a témán dolgozott, bár a portolásnál én voltam a reflektorfényben. De bár megtettem, ez nem jelenti azt, hogy a több százezer sornyi kóddal foglalkoztam, vagy akár át is ugrottam. A kódot és a naplókat országszerte elemezték a mérnökök, de amikor elmondták hipotéziseiket a hiba okairól, fél percbe telt, mire megcáfoltam őket. És amikor felkértek, hogy elemezzem az elméleteket, átadtam valaki másnak, mert nyilvánvaló volt számomra, hogy ezek a mérnökök rossz úton járnak. Beképzeltnek hangzik? Igen, de én más okból utasítottam el a hipotéziseket és kéréseket.

Megértettem a probléma természetét. Nem tudtam pontosan, hol és miért, de tudtam, hogy mi történik.

Az évek során rengeteg tudást és tapasztalatot halmoztam fel. Az Ada használatának egyik úttörője voltam, megértettem előnyeit és hátrányait. Tudom, hogy az Ada futásidejű könyvtárak hogyan dolgozzák fel a feladatokat és hogyan kezelik a párhuzamos végrehajtást. És értem az alacsony szintű programozást memória, regiszterek és assembler szinten. Vagyis mély ismeretekkel rendelkezem a szakterületemen. És ezek alapján kerestem meg a probléma okát. Nemcsak megkerültem a hibát, de megértettem, hogyan lehet megtalálni egy nagyon érzékeny futási környezetben.

A kóddal való küzdelem ilyen történetei nem túl érdekesek azok számára, akik nem ismerik az ilyen küzdelem jellemzőit és feltételeit. De ezek a történetek segítenek megérteni, mi kell az igazán nehéz problémák megoldásához.

Az igazán nehéz problémák megoldásához többnek kell lennie, mint egyszerűen programozónak. Meg kell értened a kód „sorsát”, azt, hogy hogyan kölcsönhatásba lép a környezetével, és hogyan működik maga a környezet.

És akkor lesz saját tönkretett ünnepi heted.

Продолжение следует.

Forrás: will.com

Hozzászólás