Фолклор програмера и инжењера (1. део)

Фолклор програмера и инжењера (1. део)

Ово је избор прича са интернета о томе како бубице понекад имају потпуно невероватне манифестације. Можда и ви имате нешто да кажете.

Алергија на ауто на сладолед од ваниле

Прича за инжењере који схватају да очигледно није увек одговор, и да ма колико чињенице изгледале натегнуте, оне су и даље чињенице. Понтиац дивизија Генерал Моторс Цорпоратион примила је жалбу:

Ово је други пут да вам пишем и не замерам вам што нисте одговорили, јер звучи сулудо. Наша породица има традицију да свако вече после вечере једе сладолед. Врсте сладоледа се мењају сваки пут, а после вечере цела породица бира који ће сладолед да купи, после чега идем у продавницу. Недавно сам купио нови Понтиац и од тада су моја путовања по сладолед постали проблем. Видите, сваки пут када купим сладолед од ваниле и вратим се из продавнице, ауто неће да упали. Ако донесем неки други сладолед, ауто упали без проблема. Желим да поставим озбиљно питање, ма колико глупо звучало: „Шта је то у вези са Понтиаком због чега се не покреће када донесем сладолед од ваниле, већ се лако покреће када донесем други укус сладоледа?“

Као што можете замислити, председник дивизије је био скептичан у вези са писмом. Међутим, за сваки случај послао сам инжењера да провери. Био је изненађен што га је дочекао имућан, добро образован човек који живи у прелепом крају. Договорили су се да се нађу одмах после вечере како би њих двоје отишли ​​у продавницу на сладолед. Те вечери је била ванила, а када су се вратили у кола, није хтело да упали.

Инжењер је дошао још три вечери. Први пут је сладолед био чоколадни. Ауто је кренуо. Други пут је био сладолед од јагода. Ауто је кренуо. Треће вечери је тражио да узме ванилу. Ауто није упалио.

Рационално образлажући, инжењер је одбио да верује да је аутомобил алергичан на сладолед од ваниле. Због тога сам се договорио са власником аутомобила да настави са посетама док не нађе решење за проблем. И успут је почео да бележи: записивао је све податке, доба дана, врсту бензина, време доласка и повратка из продавнице итд.

Инжењер је убрзо схватио да је власник аутомобила мање времена трошио на куповину сладоледа од ваниле. Разлог је био распоред робе у продавници. Сладолед од ваниле био је најпопуларнији и држан је у засебном замрзивачу испред продавнице како би се лакше пронашао. А све остале сорте су биле у задњем делу продавнице, и требало је много више времена да се пронађе права сорта и плати.

Сада је било питање за инжењера: зашто се аутомобил није покренуо ако је прошло мање времена од тренутка када је мотор искључен? Пошто је проблем било време, а не сладолед од ваниле, инжењер је брзо пронашао одговор: то је била гасна брава. То се дешавало сваке вечери, али када је власник аутомобила провео више времена тражећи сладолед, мотор је успео да се довољно охлади и лако се упали. А када је човек купио сладолед од ваниле, мотор је још увек био превише врућ и гасна брава није имала времена да се раствори.

Морал: Чак су и потпуно луди проблеми понекад стварни.

Црасх Бандицоот

Болно је искусити ово. Као програмер, навикнете се да кривите свој код прво, друго, треће... а негде на десетохиљадитом месту кривите компајлер. И даље на листи већ кривите опрему.

Ево моје приче о хардверској грешци.

За игру Црасх Бандицоот написао сам код за учитавање и чување на меморијској картици. За тако самозадовољног програмера игара, то је било као шетња парком: мислио сам да ће посао трајати неколико дана. Међутим, завршио сам са отклањањем грешака у коду шест недеља. Успут сам решавао и друге проблеме, али сам се сваких неколико дана враћао на овај код на неколико сати. Била је то агонија.

Симптом је изгледао овако: када сачувате тренутно играње игре и приступите меморијској картици, готово увек све иде у реду... Али понекад операција читања или писања истекне без очигледног разлога. Кратак снимак често оштети меморијску картицу. Када играч покуша да спасе, он не само да не успева да спаси, већ и уништава мапу. Срање.

После неког времена, наша продуценткиња у Сонију, Цонние Бус, почела је да паничи. Нисмо могли да испоручимо игру са овом грешком, а шест недеља касније нисам разумео шта је узрок проблема. Преко Конија смо контактирали друге програмере ПС1: да ли је неко наишао на нешто слично? Не. Нико није имао проблема са меморијском картицом.

Када немате идеје за отклањање грешака, једини приступ који преостаје је „завади па владај“: уклоните све више и више кода из неисправног програма док не остане релативно мали фрагмент који и даље изазива проблем. То јест, одсецате програм део по део док не остане део који садржи грешку.

Али ствар је у томе што је веома тешко изрезати комаде из видео игре. Како га покренути ако сте уклонили код који емулира гравитацију? Или цртање ликова?

Због тога морамо да заменимо читаве модуле стубовима који се претварају да раде нешто корисно, а у ствари раде нешто веома једноставно што не може да садржи грешке. Морамо да напишемо такве штаке да би утакмица макар радила. Ово је спор и болан процес.

Укратко, успео сам. Уклонио сам све више и више делова кода док ми није остао почетни код који конфигурише систем за покретање игре, иницијализује хардвер за рендеровање итд. Наравно, у овој фази нисам могао да направим мени за чување и учитавање, јер бих морао да направим стуб за сав графички код. Али могао бих да се претварам да сам корисник користећи (невидљиви) екран за чување и учитавање и тражим да сачувам, а затим упишем на меморијску картицу.

Ово ми је оставило мали део кода који је и даље имао горњи проблем - али се и даље дешавао насумично! Најчешће је све функционисало добро, али повремено је било грешака. Уклонио сам скоро сав код игре, али грешка је још увек жива. Ово је било збуњујуће: преостали код заправо није урадио ништа.

У неком тренутку, вероватно око три ујутру, пала ми је мисао. Операције читања и писања (унос/излаз) укључују прецизна времена извршења. Када радите са чврстим диском, меморијском картицом или Блуетоотх модулом, код ниског нивоа одговоран за читање и писање то чини у складу са импулсима сата.

Уз помоћ сата, уређај који није директно повезан са процесором се синхронизује са кодом који се извршава на процесору. Сат одређује брзину преноса података — брзину којом се преносе подаци. Ако постоји забуна са тајмингом, онда су или хардвер или софтвер, или обоје, такође збуњени. А ово је веома лоше, јер подаци могу бити оштећени.

Шта ако нешто у нашем коду збуни тајминге? Проверио сам све у вези са овим у коду програма за тестирање и приметио сам да смо програмибилни тајмер у ПС1 поставили на 1 кХз (1000 тикова у секунди). Ово је доста; подразумевано, када се конзола покрене, ради на 100 Хз. И већина игара користи ову фреквенцију.

Енди, програмер игре, подесио је тајмер на 1 кХз како би се покрети прецизније израчунавали. Енди има тенденцију да претера, и ако опонашамо гравитацију, радимо то што је могуће прецизније!

Али шта ако је убрзање тајмера некако утицало на укупно време програма, а самим тим и на сат који регулише брзину преноса за меморијску картицу?

Прокоментарисао сам тајмер код. Грешка се није поновила. Али то не значи да смо то поправили, јер се квар догодио насумично. Шта ако сам само имао среће?

Неколико дана касније поново сам експериментисао са програмом тестирања. Грешка се није поновила. Вратио сам се на пуну базу кода игре и изменио код за чување и учитавање тако да се програмибилни тајмер ресетује на своју првобитну вредност (100Хз) пре приступа меморијској картици, а затим поново на 1кХз. Више није било судара.

Али зашто се то догодило?

Поново сам се вратио на програм тестирања. Покушао сам да пронађем неки образац у појави грешке са тајмером од 1 кХз. На крају сам приметио да се грешка јавља када се неко игра са ПС1 контролером. Пошто бих то ретко радио сам - зашто би ми требао контролер приликом тестирања кода за чување и учитавање? - Нисам ни приметио ову зависност. Али једног дана ме је један од наших уметника чекао да завршим тестирање – вероватно сам у том тренутку псовао – и нервозно вртео контролор у рукама. Дошло је до грешке. "Чекај шта?!" Па, уради то поново!”

Када сам схватио да су ова два догађаја међусобно повезана, могао сам лако да репродукујем грешку: почео сам да снимам на меморијску картицу, померио контролер и уништио меморијску картицу. Мени је то изгледало као хардверска грешка.

Дошао сам код Кони и испричао јој о свом открићу. Пренела је информације једном од инжењера који су дизајнирали ПС1. „Немогуће,“ одговорио је, „не може бити хардверски проблем.“ Замолио сам Цонние да договори разговор за нас.

Инжењер ме је позвао и посвађали смо се на његовом сломљеном енглеском и мом (екстремно) сломљеном јапанском. На крају сам рекао: „Дозволите ми да пошаљем свој програм за тестирање од 30 линија где померање контролера изазива грешку.“ Он се сложио. Рекао је да је то губљење времена и да је ужасно заузет радом на новом пројекту, али би попустио јер смо ми били веома важан програмер за Сони. Очистио сам свој тестни програм и послао му га.

Следеће вечери (ми смо били у Лос Анђелесу, а он у Токију) назвао ме је и стидљиво се извинио. То је био хардверски проблем.

Не знам шта је тачно била грешка, али из онога што сам чуо у седишту компаније Сони, ако тајмер подесите на довољно високу вредност, он је ометао компоненте на матичној плочи у близини кристала тајмера. Један од њих је био контролер брзине преноса за меморијску картицу, који је такође подешавао брзину преноса за контролере. Нисам инжењер, па сам можда нешто забрљао.

Али суштина је да је било сметњи између компоненти на матичној плочи. А приликом истовременог преноса података кроз порт контролера и порт меморијске картице са тајмером који ради на 1 кХз, битови су изгубљени, подаци су изгубљени и картица је оштећена.

Лоше краве

Осамдесетих година прошлог века, мој ментор Сергеј је написао софтвер за СМ-1980, совјетски клон ПДП-1800. Овај микрорачунар је управо инсталиран на железничкој станици у близини Свердловска, важног транспортног чворишта у СССР-у. Нови систем је дизајниран за усмеравање вагона и теретног саобраћаја. Али садржао је досадну грешку која је довела до насумичних падова и падова. Падови су се увек дешавали када би неко отишао кући увече. Али упркос детаљној истрази следећег дана, рачунар је исправно радио у свим ручним и аутоматским тестовима. Ово обично указује на стање трке или неку другу такмичарску грешку која се јавља под одређеним условима. Уморан од позива касно увече, Сергеј је одлучио да дође до дна, и пре свега да схвати који су услови у ранжирном колодвору довели до квара рачунара.

Прво је прикупио статистику свих необјашњивих падова и направио графикон по датуму и времену. Образац је био очигледан. После још неколико дана посматрања, Сергеј је схватио да може лако предвидети време будућих кварова система.

Убрзо је сазнао да је до поремећаја дошло само када је станица сортирала возове стоке из северне Украјине и западне Русије који су се упутили ка оближњој кланици. То је само по себи било чудно, јер су кланицу снабдевале фарме које се налазе много ближе, у Казахстану.

Чернобилска нуклеарна електрана експлодирала је 1986. године, а радиоактивне падавине су учиниле околна подручја ненастањивим. Огромне области у северној Украјини, Белорусији и западној Русији биле су контаминиране. Сумњајући на висок ниво радијације у вагонима који стижу, Сергеј је развио метод за тестирање ове теорије. Становништву је било забрањено да има дозиметре, па се Сергеј пријавио са неколико војника на железничкој станици. После неколико пића вотке, успео је да убеди војника да измери ниво радијације у једној од сумњивих вагона. Испоставило се да је ниво неколико пута већи од нормалних вредности.

Не само да је стока емитовала много зрачења, њен ниво је био толико висок да је довео до насумичних губитака битова у меморији СМ-1800, који се налазио у згради поред станице.

У СССР-у је постојала несташица хране, а власти су одлучиле да мешају чернобилско месо са месом из других региона земље. Ово је омогућило смањење укупног нивоа радиоактивности без губитка вредних ресурса. Сазнавши за ово, Сергеј је одмах попунио документе за емиграцију. А кварови рачунара су престали сами од себе када се ниво радијације временом смањивао.

Кроз цеви

Некада давно, Мовиетецх Солутионс је креирао софтвер за биоскопе, дизајниран за рачуноводство, продају карата и опште управљање. ДОС верзија водеће апликације била је прилично популарна међу малим и средњим ланцима биоскопа у Северној Америци. Стога није изненађујуће да је, када је објављена верзија Виндовс 95, интегрисана са најновијим екранима осетљивим на додир и самоуслужним киосцима, и опремљена свим врстама алата за извештавање, и она брзо постала популарна. Најчешће је ажурирање прошло без проблема. Локално ИТ особље је инсталирало нову опрему, пренело податке и посао је настављен. Осим када није трајало. Када би се ово догодило, компанија би послала Џејмса, са надимком „Чистач“.

Иако надимак сугерише подли тип, чистач је само комбинација инструктора, инсталатера и мајстора. Џејмс би провео неколико дана на локацији клијента састављајући све компоненте, а затим би провео још неколико дана подучавајући особље како да користи нови систем, решавајући све хардверске проблеме који су се појавили и суштински помажући софтверу у повоју.

Стога није изненађујуће што је Џејмс у овим ужурбаним временима стигао у канцеларију ујутру, и пре него што је стигао до свог стола, дочекао га је менаџер, препун кофеина преко уобичајеног.

„Бојим се да морате да одете у Анаполис, Нова Шкотска, што је пре могуће. Цео систем им се покварио, а након ноћи рада са њиховим инжењерима, не можемо да схватимо шта се догодило. Изгледа да је мрежа на серверу отказала. Али тек након што је систем радио неколико минута.

— Нису се вратили на стари систем? – одговорио је Џејмс потпуно озбиљно, иако је ментално разрогачио очи од изненађења.

— Управо тако: њихов ИТ стручњак је „променио приоритете“ и одлучио да оде са својим старим сервером. Џејмс, инсталирали су систем на шест локација и управо платили врхунску подршку, а њихов посао се сада води као 1950-их.

Џејмс се лагано усправио.

- То је друга ствар. Ок, хајде да почнемо.

Када је стигао у Анаполис, прво што је урадио је пронашао прво позориште муштерије које је имало проблем. На мапи снимљеној на аеродрому све је изгледало пристојно, али је подручје око жељене адресе изгледало сумњиво. Није гето, већ подсећа на филм ноар. Док је Џејмс паркирао на ивичњаку у центру града, пришла му је проститутка. С обзиром на величину Анаполиса, највероватније је био једини у целом граду. Њен изглед је одмах подсетио на познатог лика који је нудио секс за новац на великом екрану. Не, не о Џулији Робертс, већ о Џону Војту [алузија на филм „Поноћни каубој“ – прибл. лане].

Пославши проститутку на пут, Џејмс је отишао у биоскоп. Околина је постала боља, али је и даље остављала утисак да је дотрајала. Није да је Џејмс био превише забринут. Већ је био на бедним местима. А ово је била Канада, где су чак и пљачкаши довољно љубазни да кажу „хвала“ након што вам узму новчаник.

Бочни улаз у биоскоп био је у влажној уличици. Џејмс је пришао вратима и покуцао. Убрзо је зашкрипао и лагано се отворио.

-Јесте ли чистачица? - промукао је глас изнутра.

- Да, ја сам... Дошао сам да све поправим.

Џејмс је ушао у предворје биоскопа. Очигледно није било другог избора, особље је почело да дели папирне карте посетиоцима. То је отежавало финансијско извештавање, а камоли интересантније детаље. Али особље је дочекало Џејмса са олакшањем и одмах га одвело у собу за сервере.

На први поглед све је било у реду. Џејмс се пријавио на сервер и проверио уобичајена сумњива места. Нема проблема. Међутим, из обиља опреза, Џејмс је искључио сервер, заменио мрежну картицу и вратио систем. Одмах је почела да ради у потпуности. Особље је поново почело да продаје карте.

Џејмс је позвао Марка и обавестио га о ситуацији. Није тешко замислити да би Џејмс можда желео да остане и види да ли ће се десити нешто неочекивано. Сишао је низ степенице и почео да пита запослене шта се догодило. Очигледно је систем престао да ради. Искључили су га и укључили, све је радило. Али после 10 минута систем је пао.

Управо у овом тренутку догодило се нешто слично. Одједном је систем за продају карата почео да испушта грешке. Особље је уздахнуло и зграбило папирне карте, а Џејмс је пожурио у собу за сервере. Све је изгледало добро са сервером.

Затим је ушао један од запослених.

— Систем поново ради.

Џејмс је био збуњен јер ништа није урадио. Тачније, ништа што би натерало систем да функционише. Одјавио се, узео телефон и позвао линију подршке своје компаније. Убрзо је исти запослени ушао у серверску собу.

- Систем је пао.

Џејмс је бацио поглед на сервер. На екрану је плесао занимљив и познат образац разнобојних облика - хаотично увијање и преплитање цеви. Сви смо у неком тренутку видели овај скринсејвер. Било је лепо изведено и буквално хипнотише.


Џејмс је притиснуо дугме и образац је нестао. Пожурио је до благајне и на путу срео службеника који му се враћао.

— Систем поново ради.

Ако можете да урадите ментални фацепалм, то је управо оно што је Џејмс урадио. Сцреенсавер. Користи ОпенГЛ. И стога, током рада, троши све ресурсе серверског процесора. Као резултат, сваки позив серверу завршава се тимеоутом.

Џејмс се вратио у серверску собу, пријавио се и заменио скринсејвер прелепим цевима са празним екраном. То јест, уместо скринсејвера који троши 100% процесорских ресурса, инсталирао сам други који не троши ресурсе. Онда сам чекао 10 минута да проверим своју претпоставку.

Када је Џејмс стигао у следећи биоскоп, питао се како да објасни свом менаџеру да је управо прелетео 800 км да би искључио чувар екрана.

Пад током одређене фазе месеца

Истинита прича. Једног дана појавила се софтверска грешка која је зависила од фазе месеца. Постојала је мала рутина која се обично користила у разним МИТ програмима за израчунавање апроксимације правој фази Месеца. ГЛС је ову рутину уградио у ЛИСП програм који би, приликом писања датотеке, избацио ред са временском ознаком дугачком скоро 80 ​​знакова. Врло ретко је било да би први ред поруке био предугачак и водио до следећег реда. А када је програм касније прочитао ову датотеку, опсовао је. Дужина првог реда зависила је од тачног датума и времена, као и од дужине спецификације фазе у време штампања временске ознаке. То јест, буба је буквално зависила од фазе месеца!

Прво папирно издање Жаргон Филе (Стееле-1983) је садржао пример такве линије која је довела до описане грешке, али ју је слагач „поправио”. Ово је од тада описано као "буба у фази Месеца".

Ипак, будите опрезни са претпоставкама. Пре неколико година, инжењери из ЦЕРН-а (Европски центар за нуклеарна истраживања) наишли су на грешке у експериментима спроведеним на Великом сударачу електрона и позитрона. Пошто рачунари активно обрађују огромну количину података које генерише овај уређај пре него што покажу резултат научницима, многи су спекулисали да је софтвер на неки начин осетљив на фазу Месеца. Неколико очајних инжењера је дошло до дна истине. Грешка је настала услед незнатне промене геометрије 27 км дугог прстена услед деформације Земље током проласка Месеца! Ова прича је ушла у фолклор физике као „Њутнова освета физици честица“ и пример везе између најједноставнијих и најстаријих закона физике и најнапреднијих научних концепата.

Испирање тоалета зауставља воз

Најбоља хардверска грешка за коју сам икада чуо била је у брзом возу у Француској. Буба је довела до наглог кочења воза, али само ако је у њему било путника. У сваком таквом случају воз је стављен ван саобраћаја, провераван, али ништа није пронађено. Затим је враћен на линију, и он је одмах стао.

Током једне од провера, инжењер који је путовао у возу отишао је у тоалет. Убрзо је опрао, БУМ! Хитно заустављање.

Инжењер је контактирао возача и питао:

— Шта сте радили непосредно пре кочења?

- Па, успорио сам на спусту...

Ово је било чудно, јер током нормалног рада воз успорава на спуштању на десетине пута. Воз је кренуо даље, а при следећем спуштању машиновођа је упозорио:

- Успорићу.

Ништа се није десило.

— Шта сте радили при последњем кочењу? – упитао је возач.

- Па... био сам у тоалету...

- Па, онда иди у тоалет и уради оно што си урадио кад опет сиђемо!

Инжењер је отишао у тоалет, а када је возач упозорио: „Успорим“, испустио је воду. Наравно, воз је одмах стао.

Сада су могли да репродукују проблем и морали су да пронађу узрок.

После два минута приметили су да је кабл за даљинско управљање моторном кочницом (воз је имао по један мотор на сваком крају) био искључен са зида електро ормана и да лежи на релеју који је контролисао соленоид утикача тоалета... Када је релеј био укључен, стварао је сметње у каблу кочнице, а заштита система од кварова једноставно је укључивала кочење у нужди.

Капија која је мрзела ФОРТРАН

Пре неколико месеци приметили смо да мрежне везе на копну [ово је било на Хавајима] постају веома, веома споре. Ово може трајати 10-15 минута, а затим се изненада поновити. После неког времена, колега ми се пожалио да су мрежне везе на копну уопште не ради. Имао је неки ФОРТРАН код који је требало копирати на машину на копну, али није могао јер „мрежа није издржала довољно дуго да се ФТП отпремање заврши“.

Да, испоставило се да је дошло до кварова на мрежи када је колега покушао да ФТП фајл са изворним кодом на ФОРТРАН-у пренесе на машину на копну. Покушали смо да архивирамо датотеку: онда је глатко копирана (али циљна машина није имала распакивач, тако да проблем није решен). Коначно смо "разделили" ФОРТРАН код на веома мале делове и послали их један по један. Већина фрагмената је копирана без проблема, али неколико комада није прошло, или је прошло бројни покушаји.

Када смо испитали проблематичне пасусе, открили смо да имају нешто заједничко: сви су садржали блокове коментара који су почињали и завршавали се редовима који се састоје од великог Ц (као што је колега више волео да коментарише у ФОРТРАНУ). Послали смо е-пошту мрежним стручњацима на копну и затражили помоћ. Наравно, желели су да виде узорке наших фајлова који се не могу пренети преко ФТП-а... али наша писма нису стигла до њих. Коначно смо дошли до једноставног описатикако изгледају непреносиви фајлови. Успело је :) [Да ли да додам пример једног од проблематичних ФОРТРАН коментара овде? Вероватно није вредно тога!]

На крају смо успели да то схватимо. Недавно је постављен нови пролаз између нашег дела кампуса и копнене мреже. Имао је ОГРОМНЕ потешкоће при преношењу пакета који су садржали поновљене битове великих слова Ц! Само неколико од ових пакета може заузети све ресурсе мрежног пролаза и спречити већину других пакета да прођу. Пожалили смо се произвођачу гатеваи-а... а они су одговорили: „О, да, суочени сте са грешком поновљеног Ц! Већ знамо за њега.” На крају смо решили проблем куповином новог гејтвеја од другог произвођача (у одбрану првог, немогућност преноса ФОРТРАН програма може бити предност за неке!).

Тешка времена

Пре неколико година, док сам радио на креирању ЕТЛ система у Перлу да бих смањио трошкове клиничких испитивања фазе 40, морао сам да обрадим око 000 датума. Њих двоје нису положили тест. Ово ме није превише засметало јер су ови датуми узети из података које је дао клијент који је често био, да тако кажемо, изненађујући. Али када сам проверио оригиналне податке, испоставило се да су то били 1. јануар 2011. и 1. јануар 2007. Мислио сам да је грешка садржана у програму који сам управо написао, али се испоставило да је већ прошло 30 година. стари. Ово може звучати мистериозно за оне који нису упознати са софтверским екосистемом. Због дугогодишње одлуке друге компаније да заради новац, мој клијент ми је платио да поправим грешку коју је једна компанија увела случајно, а друга намерно. Да бисте разумели о чему говорим, морам да говорим о компанији која је додала функцију која је на крају постала грешка, као и о неколико других занимљивих догађаја који су допринели мистериозној грешци коју сам исправио.

У стара добра времена, Аппле рачунари би понекад спонтано ресетовали датум на 1. јануар 1904. Разлог је био једноставан: користио је „системски сат“ на батерије за праћење датума и времена. Шта се десило када се батерија испразнила? Рачунари су почели да прате датум по броју секунди од почетка епохе. Под епохом смо подразумевали референтни оригинални датум, а за Мацинтосх је то био 1. јануар 1904. А након што се батерија испразнила, тренутни датум је ресетован на наведени. Али зашто се то догодило?

Раније је Аппле користио 32 бита за чување броја секунди од првобитног датума. Један бит може да ускладишти једну од две вредности - 1 или 0. Два бита могу да складиште једну од четири вредности: 00, 01, 10, 11. Три бита - једна вредност од осам: 000, 001, 010, 011, 100 , 101, 110, 111 итд. А 32 би могао да сачува једну од 232 вредности, односно 4 секунди. За Аппле датуме, ово је било око 294 година, тако да старији Мац рачунари не могу да обрађују датуме након 967. А ако се батерија система испразни, датум се ресетује на 296 секунди од почетка епохе и морате ручно да подесите датум сваки пут када укључите рачунар (или док не купите нову батерију).

Међутим, Аппле-ова одлука да чува датуме као секунде од епохе значила је да нисмо могли да обрађујемо датуме пре епохе, што је имало далекосежне последице, као што ћемо видети. Аппле је представио функцију, а не грешку. Између осталог, то је значило да је Мацинтосх оперативни систем имун на „миленијумску грешку“ (што се не може рећи за многе Мац апликације које су имале сопствене системе датума да би заобишли ограничења).

Хајде. Користили смо Лотус 1-2-3, ИБМ-ову „убиствену апликацију“ која је помогла да се покрене ПЦ револуција, иако су Аппле рачунари имали ВисиЦалц, због чега је лични рачунар био успешан. Искрено речено, да се 1-2-3 није појавио, ПЦ тешко да би узели маха, а историја персоналних рачунара могла би се развијати сасвим другачије. Лотус 1-2-3 је погрешно третирао 1900. као преступну годину. Када је Мицрософт објавио своју прву табелу, Мултиплан, заузео је мали удео на тржишту. А када су покренули Екцел пројекат, одлучили су не само да копирају шему именовања редова и колона из Лотуса 1-2-3, већ и да обезбеде компатибилност са грешкама намерно третирајући 1900. као преступну годину. Овај проблем постоји и данас. Дакле, у 1-2-3 то је била грешка, али у Екцел-у је била свесна одлука да се осигура да сви 1-2-3 корисници могу да увезу своје табеле у Екцел без промене података, чак и ако су погрешни.

Али постојао је још један проблем. Прво, Мицрософт је издао Екцел за Мацинтосх, који није признавао датуме пре 1. јануара 1904. А у Екцелу се 1. јануар 1900. сматрао почетком ере. Стога су програмери направили промену тако да је њихов програм препознао тип ере и ускладиштио податке у себи у складу са жељеном ером. Мицрософт је чак написао чланак са објашњењем о томе. И ова одлука је довела до моје грешке.

Мој ЕТЛ систем је примио Екцел табеле од купаца које су креиране на Виндовс-у, али се такође могу креирати на Мац-у. Дакле, почетак ере у табели могао би бити или 1. јануар 1900. или 1. јануар 1904. године. Како сазнати? Формат Екцел датотеке показује потребне информације, али парсер који сам користио није их показао (сада јесте), и претпоставља да знате епоху за одређену табелу. Вероватно сам могао да потрошим више времена на разумевање бинарног формата Екцел-а и слање закрпе аутору парсера, али сам имао још много тога да урадим за клијента, па сам брзо написао хеуристику да одредим епоху. Била је једноставна.

У Екцел-у се датум 5. јул 1998. може представити у формату „07-05-98“ (бескорисни амерички систем), „5. јул 98.“, „5. јул 1998.“, „5. јул-98.“ или неки други формат.још један бескорисни формат (иронично, један од формата који моја верзија Екцел-а није нудила био је ИСО 8601). Међутим, у оквиру табеле, неформатирани датум је сачуван као „35981“ за епоху-1900 или „34519“ за епоху-1904 (бројеви представљају број дана од епохе). Једноставно сам користио једноставан парсер да издвојим годину из форматираног датума, а затим користим Екцел парсер да издвојим годину из неформатираног датума. Ако су се обе вредности разликовале за 4 године, онда сам знао да користим систем са епохом-1904.

Зашто једноставно нисам користио форматиране датуме? Зато што се 5. јул 1998. може форматирати као „јули 98.“ са изгубљеним даном у месецу. Добили смо табеле од толико компанија које су их креирале на толико различитих начина да је на нама (у овом случају, мени) било да одредимо датуме. Осим тога, ако Екцел то добро схвати, онда би и ми требали!

Истовремено сам наишао на 39082. Дозволите ми да вас подсетим да је Лотус 1-2-3 сматрао 1900. преступном годином, и то је верно поновљено у Екцел-у. А пошто је ово додао један дан 1900. години, многе функције израчунавања датума могле би бити погрешне за тај дан. То јест, 39082 је могло бити 1. јануара 2011. (на Мац рачунарима) или 31. децембра 2006. (на Виндовс-у). Ако је мој „парсер године“ издвојио 2011. годину из форматиране вредности, онда је све у реду. Али пошто Екцел парсер не зна која се епоха користи, подразумевано је епоха-1900, враћајући 2006. годину. Моја апликација је видела да је разлика 5 година, сматрала је то грешком, забележила је и вратила неформатирану вредност.

Да бих ово заобишао, написао сам ово (псеудокод):

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

А онда је свих 40 датума рашчлањено исправно.

Усред великих послова штампања

Почетком 1980-их, мој отац је радио у Стораге Тецхнологи, сада угашеном одељењу које је креирало погоне трака и пнеуматске системе за брзо пуњење траке.

Редизајнирали су диск јединице тако да могу имати један централни „А“ диск повезан са седам „Б“ дискова, а мали ОС у РАМ-у који је контролисао „А“ диск могао је делегирати операције читања и писања на све „Б“ дискове.

Сваки пут када је диск „А” покренут, било је потребно убацити флопи диск у периферни драјв повезан на „А” како би се оперативни систем учитао у његову меморију. Било је изузетно примитивно: рачунарску снагу је обезбеђивао 8-битни микроконтролер.

Циљна публика за овакву опрему биле су компаније са веома великим складиштима података - банке, малопродајни ланци, итд. - којима је било потребно да штампају много адресних налепница или банковних извода.

Један клијент је имао проблем. Усред задатка штампања, један одређени диск „А“ би могао да престане да ради, што би довело до застоја целог посла. Да би вратили рад диска, особље је морало да све поново покрене. А ако се ово догодило усред шестосатног задатка, онда је изгубљено огромно скупо компјутерско време и поремећен је распоред читаве операције.

Техничари су послати из Стораге Тецхнологиес. Али упркос њиховим најбољим напорима, нису успели да репродукују грешку под условима тестирања: чинило се да се појавила усред великих задатака за штампање. Проблем није био хардвер, заменили су све што су могли: РАМ, микроконтролер, флопи драјв, сваки замисливи део траке - проблем је и даље присутан.

Тада су техничари позвали штаб и позвали Експерта.

Стручњак је зграбио столицу и шољицу кафе, сео у компјутерску салу — у то време постојале су собе посвећене компјутерима — и посматрао како особље чека велики посао за штампање. Експерт је чекао да дође до неуспеха - и јесте. Сви су гледали у Експерта, али он није имао појма зашто се то догодило. Зато је наредио да се посао поново стави у ред, а сво особље и техничари су се вратили на посао.

Стручњак је поново сео у столицу и почео да чека неуспех. Прошло је око шест сати и дошло је до квара. Експерт опет није имао идеје, осим да се све дешавало у просторији пуној људи. Наредио је да се мисија поново покрене, сео је и чекао.

До трећег неуспеха, Експерт је нешто приметио. До квара је дошло када је особље променило траке на страном диску. Штавише, квар је настао чим је један од запослених прошао кроз одређену плочицу на поду.

Уздигнути под је направљен од алуминијумских плочица постављених на висини од 6 до 8 инча. Бројне жице из компјутера су пролазиле испод подигнутог пода како би спречиле да неко случајно нагази важан кабл. Плочице су биле постављене веома чврсто како би се спречило да остаци доспеју испод подигнутог пода.

Стручњак је схватио да је једна плочица деформисана. Када је запослени стао на његов угао, ивице плочице су трљале о суседне плочице. Са њима су се трљали и пластични делови који су спајали плочице, што је изазвало статичка микропражњења која су стварала радио-фреквентне сметње.

Данас је РАМ много боље заштићен од радиофреквентних сметњи. Али тих година то није био случај. Стручњак је схватио да је ова сметња пореметила меморију, а са њом и рад оперативног система. Позвао је службу за подршку, наручио нове плочице, сам их поставио и проблем је нестао.

Плима је!

Прича се одиграла у серверској соби, на четвртом или петом спрату канцеларије у Портсмуту (мислим), у зони докова.

Једног дана се срушио Уник сервер са главном базом података. Поново су га покренули, али је он срећно наставио да пада изнова и изнова. Одлучили смо да позовемо некога из службе за подршку.

Момак из подршке... Мислим да се звао Марк, али то није важно... Мислим да га не познајем. Није важно, заиста. Хајде да се држимо Марка, ок? Велики.

Дакле, неколико сати касније Марк је стигао (није далек пут од Лидса до Портсмута, знате), укључио сервер и све је радило без проблема. Типична проклета подршка, клијент се веома узнемири због тога. Марк прегледа датотеке евиденције и не налази ништа лоше. Дакле, Марк се враћа у воз (или којим год начином превоза је стигао, могла је то бити хрома крава колико знам... у сваком случају, нема везе, у реду?) и креће назад у Лидс, протраћивши дан.

Исте вечери сервер се поново руши. Прича је иста... сервер се не диже. Марк покушава да помогне даљински, али клијент не може да покрене сервер.

Још један воз, аутобус, безе од лимуна или неко друго срање, и Марк се вратио у Портсмут. Видите, сервер се покреће без проблема! Чудо. Марк проводи неколико сати проверавајући да ли је све у реду са оперативним системом или софтвером и креће за Лидс.

Отприлике средином дана сервер се руши (само полако!). Овај пут се чини разумним да се доведу људи за подршку за хардвер да замене сервер. Али не, после око 10 сати и она пада.

Ситуација се понављала неколико дана. Сервер ради, руши се након око 10 сати и не покреће се наредна 2 сата. Проверили су хлађење, цурење меморије, проверили све, али ништа нису нашли. Онда су падови престали.

Недеља је прошла безбрижно... сви су били срећни. Срећан док све не почне поново. Слика је иста. 10 сати рада, 2-3 сата застоја...

А онда је неко (мислим да су ми рекли да та особа нема никакве везе са ИТ) рекао:

"То је плима!"

Узвик је дочекан празним погледима, а нечија рука је вероватно оклевала на дугмету за безбедносни позив.

"Престаје да ради са плимом."

Ово би изгледало као потпуно стран концепт радницима ИТ подршке, који вероватно неће читати Годишњак Тиде док седе на кафи. Објаснили су да то никако не може бити повезано са плимом, јер је сервер радио недељу дана без кварова.

„Прошле недеље је плима била ниска, али ове недеље је висока.

Мало терминологије за оне који немају дозволу за јахту. Плима и осека зависе од лунарног циклуса. И док се Земља ротира, сваких 12,5 сати гравитациона сила Сунца и Месеца ствара плимни талас. На почетку циклуса од 12,5 сати је плима, средином циклуса је осека, а на крају поново плима. Али како се месечева орбита мења, тако се мења и разлика између осеке и осеке. Када се Месец налази између Сунца и Земље или на супротној страни Земље (пун месец или без месеца), добијамо плиму и осеку Сизигин - највеће плиме и најниже осеке. На пола месеца добијамо квадратурне плиме - најниже плиме. Разлика између ова два екстрема се значајно смањује. Месечев циклус траје 28 дана: сизигијан – квадратура – ​​сизигијан – квадратура.

Када је техничарима објашњена суштина плимних сила, одмах су помислили да треба да позову полицију. И сасвим логично. Али испоставило се да је тип био у праву. Две недеље раније, недалеко од канцеларије привезан је разарач. Сваки пут када би га плима подигла на одређену висину, бродски радарски стуб би завршио на нивоу пода серверске собе. А радар (или опрема за електронско ратовање, или нека друга војна играчка) је створио хаос у компјутерима.

Летна мисија за ракету

Добио сам задатак да пренесем велики (око 400 хиљада линија) систем за контролу и праћење лансирања ракета на нове верзије оперативног система, компајлера и језика. Тачније, од Солариса 2.5.1 до Солариса 7, и од Вердик Ада развојног система (ВАДС), написаног у Ади 83, до Ратионал Апек Ада система, написаног у Ада 95. ВАДС је купио Ратионал, а његов производ је застарело, иако је Ратионал покушао да имплементира компатибилне верзије пакета специфичних за ВАДС да би олакшао прелазак на Апек компајлер.

Три особе су ми помогле да чисто компајлирам код. Требало је две недеље. А онда сам сам радио на томе да систем функционише. Укратко, то је била најгора архитектура и имплементација софтверског система са којом сам се сусрео, тако да је требало још два месеца да се заврши порт. Систем је потом предат на тестирање, које је трајало још неколико месеци. Одмах сам исправио грешке које су пронађене током тестирања, али се њихов број брзо смањио (изворни код је био производни систем, па је његова функционалност функционисала прилично поуздано, само сам морао да уклоним грешке које су настале током адаптације на нови компајлер). На крају, када је све функционисало како треба, пребачен сам на други пројекат.

А у петак пред Дан захвалности зазвонио је телефон.

Лансирање ракете требало је да буде тестирано за око три недеље, а током лабораторијских испитивања одбројавања блокиран је низ команди. У стварном животу, ово би прекинуло тестирање, а ако би до блокаде дошло у року од неколико секунди од покретања мотора, у помоћним системима би се десило неколико неповратних радњи, које би захтевале дугу - и скупу - спремност ракете. Не би почело, али би многи људи били веома узнемирени због губитка времена и много, много новца. Немојте дозволити да вам неко каже да Министарство одбране несмотрено троши новац—никада нисам срео менаџера који је извршио уговоре који није ставио буџет на прво или друго место, а затим на распоред.

Претходних месеци, овај изазов одбројавања је покренут стотине пута у многим варијантама, са само неколико мањих штуцања. Тако да је вероватноћа да се то догоди била веома мала, али су последице биле веома значајне. Помножите оба ова фактора и схватићете да су вести предвиделе уништену празничну недељу за мене и десетине инжењера и менаџера.

И пажња је посвећена мени као особи која је портирала систем.

Као и код већине безбедносно критичних система, много параметара је евидентирано, тако да је било прилично лако идентификовати неколико линија кода које су извршене пре него што се систем срушио. И наравно, није било апсолутно ничег необичног у вези са њима; исти изрази су успешно изведени буквално хиљадама пута током исте вожње.

Позвали смо људе из Апека у Ратионал јер су они ти који су развили компајлер и неке од рутина које су развили биле су позване у сумњивом коду. Они (и сви остали) су били импресионирани да постоји потреба да се дође до корена проблема од дословно националног значаја.

Пошто у часописима није било ништа занимљиво, одлучили смо да покушамо да репродукујемо проблем у локалној лабораторији. Ово није био лак задатак, јер се догађај дешавао отприлике једном на 1000 вожњи. Један од разлога за сумњу је био позив на мутек функцију коју је развио произвођач (део ВАДС пакета за миграцију) Unlock није довело до откључавања. Нит за обраду која је позвала функцију обрађивала је поруке откуцаја срца, које су номинално стизале сваке секунде. Подигли смо фреквенцију на 10 Хз, односно 10 пута у секунди, и почели да трчимо. Отприлике сат времена касније систем се сам закључао. У дневнику смо видели да је редослед снимљених порука исти као и током неуспелог теста. Направили смо још неколико вожњи, систем је константно блокиран 45-90 минута након старта, и сваки пут је дневник садржао исту руту. Иако смо технички користили другачији код – учесталост порука је била другачија – понашање система је било исто, тако да смо били уверени да овај сценарио учитавања изазива исти проблем.

Сада је требало да схватимо где је тачно дошло до блокирања у низу израза.

Ова имплементација система користила је систем задатака Ада, и користила га је невероватно лоше. Задаци су паралелно извршна конструкција високог нивоа у Ади, нешто попут нити извршавања, само уграђена у сам језик. Када два задатка треба да комуницирају, они „одговарају састанак”, размењују потребне податке, а затим заустављају састанак и враћају се на своја независна извршења. Међутим, систем је имплементиран другачије. Након што је циљни задатак био рандеву, тај циљни задатак се састајао са другим задатком, који се затим састајао са трећим задатком, и тако даље док се нека обрада не заврши. Након овога, сви ови састанци су завршени и сваки задатак је морао да се врати свом извршењу. Односно, радили смо са најскупљим системом позивања функција на свету, који је зауставио цео процес „мултитаскинг“ док је обрађивао део улазних података. А раније то није доводило до проблема само зато што је пропусност била веома мала.

Описао сам овај механизам задатка јер када је састанак био затражен или се очекивао да ће се завршити, може доћи до „промена задатака“. То јест, процесор би могао да почне да обрађује други задатак који је спреман за извршење. Испоставило се да када је један задатак спреман за састанак са другим задатком, потпуно другачији задатак може почети да се извршава, и на крају се контрола враћа на први састанак. И други догађаји могу да доведу до промене задатка; један такав догађај је позив системској функцији, као што је штампање или извршавање мутекса.

Да бих разумео која линија кода изазива проблем, морао сам да пронађем начин да забележим напредак кроз низ наредби без активирања прекидача задатка, што би спречило да дође до пада. Тако да нисам могао да искористим предност Put_Line()да се избегне извођење И/О операција. Могао бих да поставим променљиву бројача или нешто слично, али како да видим њену вредност ако не могу да је прикажем на екрану?

Такође, приликом испитивања дневника, показало се да, упркос томе што је висила обрада срчаних порука, која је блокирала све И/О операције процеса и онемогућавала обављање друге обраде, остали независни задаци су наставили да се извршавају. Односно, рад није у потпуности блокиран, већ само (критични) ланац задатака.

Ово је био траг потребан за процену блокирајућег израза.

Направио сам Ада пакет који је садржао задатак, набројани тип и глобалну променљиву тог типа. Бројни литерали били су везани за специфичне изразе проблематичне секвенце (нпр. Incrementing_Buffer_Index, Locking_Mutex, Mutex_Unlocked), а затим је у њега уметнуо изразе за доделу који су доделили одговарајуће набрајање глобалној променљивој. Пошто је објектни код свега овога једноставно ускладиштио константу у меморији, пребацивање задатака као резултат његовог извршења је било крајње мало вероватно. Пре свега смо били сумњичави према изразима који би могли да промене задатак, пошто је до блокирања дошло приликом извршавања, а не до враћања при пребацивању задатка назад (из неколико разлога).

Задатак праћења се једноставно одвијао у петљи и периодично проверавао да ли се вредност глобалне променљиве променила. Са сваком променом, вредност је сачувана у датотеци. Затим кратко чекање и нова провера. Написао сам променљиву у датотеку јер је задатак био извршен само када га је систем изабрао за извршење приликом пребацивања задатка у проблемској области. Шта год да се десило у овом задатку неће утицати на друге, неповезане блокиране задатке.

Очекивало се да када систем дође до тачке извршавања проблематичног кода, глобална променљива ће бити ресетована приликом преласка на сваки следећи израз. Тада ће се десити нешто што доводи до промене задатка, а пошто је његова фреквенција извршавања (10 Хз) нижа од оне задатка надгледања, монитор би могао да ухвати вредност глобалне променљиве и да је запише. У нормалној ситуацији, могао бих да добијем понављајући низ подскупа набрајања: последње вредности променљиве у време промене задатка. Када виси, глобална променљива више не би требало да се мења, а последња уписана вредност ће указати који израз није завршен.

Покренуо сам код са праћењем. Укочио се. А надзор је радио као сат.

Дневник је садржао очекивани низ, који је прекинут вредношћу која указује да је мутекс позван Unlock, а задатак није завршен – као што је случај са хиљадама претходних позива.

Апек инжењери су грозничаво анализирали свој код у овом тренутку и пронашли место у мутексу где би, теоретски, могло доћи до закључавања. Али његова вероватноћа је била веома мала, пошто је само одређени низ догађаја који се дешавају у одређено време могао довести до блокирања. Марфијев закон, момци, то је Марфијев закон.

Да бих заштитио део кода који ми је био потребан, заменио сам позиве мутекс функција (саграђене на врху мутекс функционалности ОС) са малим изворним Ада мутек пакетом за контролу приступа мутекса том делу.

Убацио сам га у код и извршио тест. Седам сати касније код је и даље радио.

Мој код је достављен Ратионал-у, где су га компајлирали, раставили и проверили да ли не користи исти приступ који је коришћен у проблематичним мутекс функцијама.

Ово је био највећи преглед кода у мојој каријери 🙂 Са мном је било десетак инжењера и менаџера у просторији, још десет људи је било на конференцијском позиву - и сви су прегледали око 20 линија кода.

Код је прегледан, нове извршне датотеке су састављене и предате на формално регресијско тестирање. Неколико недеља касније, тест одбројавања је био успешан и ракета је полетела.

Добро, то је све у реду, али која је поента приче?

Био је то апсолутно одвратан проблем. Стотине хиљада линија кода, паралелно извршавање, преко десетина процеса у интеракцији, лоша архитектура и лоша имплементација, интерфејси за уграђене системе и потрошени милиони долара. Нема притиска, зар не.

Нисам био једини који је радио на овом проблему, иако сам био у центру пажње док сам радио портирање. Али иако сам то урадио, то не значи да сам разумео све стотине хиљада редова кода, или чак да сам их прегледао. Код и дневнике су анализирали инжењери широм земље, али када су ми рекли своје хипотезе о узроцима квара, требало ми је само пола минута да их оповргнем. А када су ме замолили да анализирам теорије, пренео бих то неком другом, јер ми је било очигледно да ови инжењери иду погрешним путем. Звучи дрско? Да, то је тачно, али сам хипотезе и захтеве одбацио из другог разлога.

Схватио сам природу проблема. Нисам знао тачно где се то дешава ни зашто, али знао сам шта се дешава.

Током година, стекао сам много знања и искуства. Био сам један од пионира коришћења Аде и разумео сам њене предности и мане. Знам како Ада рунтиме библиотеке рукују задацима и баве се паралелним извршавањем. И разумем програмирање ниског нивоа на нивоу меморије, регистара и асемблера. Другим речима, имам дубоко знање у својој области. И користио сам их да пронађем узрок проблема. Нисам само заобилазио грешку, разумео сам како да је пронађем у веома осетљивом окружењу за извршавање.

Такве приче о борби са кодом нису баш занимљиве за оне који нису упознати са карактеристикама и условима такве борбе. Али ове приче нам помажу да разумемо шта је потребно за решавање заиста тешких проблема.

Да бисте решили заиста тешке проблеме, морате бити више од програмера. Морате да разумете „судбину“ кода, како он ступа у интеракцију са својим окружењем и како само окружење функционише.

А онда ћете имати своју уништену празничну недељу.

Наставити.

Извор: ввв.хабр.цом

Додај коментар