Русский
Русский
English
Статистика
Реклама

Истории из жизни

Ящик пива за лучшую сисадминскую байку и наш личный топ историй

03.03.2021 16:23:30 | Автор: admin
Мы в очень любим три вещи: сисадминов, байки и пиво.

В этот раз мы решили объединить эти любимые вещи и сделать конкурс лучших сисадминских баек: про работу, клиентов и забавные случаи из практики.


Ммммм, сисадмин-техпод-байка-пиво

Каждому, кто расскажет забавную историю в комментариях, мы подарим по баночке нашего фирменного , а победителю, чей рассказ наберет больше всего плюсов вышлем целый ящик пива.

Для вдохновения и правильного настроя, делимся нашими любимыми сисадминскими байками: тут почти нет новых историй, зато много ностальгии, доброго юмора и даже пара нерешенных до сих пор загадок. Поехали?



Раньше я работал в IT-отделе компании Samsung. Одному из сотрудников нужно было сбросить пароль, я сменил пароль на Samsung1 и сказал ему об этом. Мне перезвонили через две минуты и сказали, что пароль не подходит. Я снова сбросил его, но он снова не сработал. Я подумал, что проблемы со стороны пользователя и решил зайти к нему.
Каково было мое удивление, когда я увидел, что он неправильно набирает пароль! Он печатал Semsung1.
Подсказываю! Это компания, в которой вы работаете, и ее название написано на мониторах, перед которыми вы сидите

Питер Дж.




Это было в начале 2007 года. В нашем колледже строили Центр обработки данных в переоборудованном классе, практически не обращая внимания на климат-контроль, а тогда там стоял обычный сплит-кондиционер. Наш колледж находился в юго-западной части пустыни Мохаве, в Южной Калифорнии. В нем экономили деньги каждые выходные отключая все кондиционеры по всему кампусу, в том числе и в центре обработки данных, так что наши серверы пыхтели при 50-60 градусной жаре до утра понедельника. В марте 2007 года мы обратились к поставщику резервных копий, так как у нас был ленточный накопитель Quantum LTO1 (только с одним отделением для кассеты), и он глючил из-за жары в нашем . Нам нужен был надежный накопитель, который бы выживал в наших условиях. Но существующее решение не могло делать копии открытых файлов, потому нам нужна была неделя на то, чтобы собрать полный набор данных (из-за медленного накопителя). Мы попросили денег на резервный узел SAN для подсраховки в случае падения, но нам отказали.

Вместо этого нам выделили деньги на работу сторонней компании, выполняющей резервное копирование в сжатые сроки. Выезд их специалистов запланировали 17 июля 2007 года в 8:45, чтобы они делали нам полный бекап. В точности по Закону Мерфи наша SAN вышла из строя ночью, прямо перед запланированным приездом специалистов по бекапу, а один из на 900 ГБ был потерян навсегда.
Да здравствует планирование!

Джастин Дж.



У нас в компании было совещание руководителей отделов для обсуждения работы с компьютерной системой службы 911. Инструкции разослали утром в пятницу, чтобы начать тренинг по работе в ней уже в понедельник.
Два пользователя, не особо вникая текст письма, активировали систему по инструкции сразу, как только получили письмо, наведя шухер среди офицеров полиции работающих в 911.

Зак Д.



Как и большинство системных администраторов я начал с работы в службе поддержки.
Однажды мне потребовалось более 20 минут, чтобы объяснить новой работнице, как нажать CTRL-ALT-DEL для входа в компьютер. Она просто не могла понять концепцию одновременного нажатия 3 клавиш сразу

Конрад Дж.



Как-то рабочий, обслуживающий коммуникации в фальш-потолке, где были проложены наши сетевые кабели, случайно их перерезал. Когда наши инженеры прибыли на место для устранения обрыва, рабочий сказал, что все в порядке, и он сам все исправил.

Он соединил обрывки витых пар колпачками для скрутки проводов.

Уоллес Ф.



Однажды я чуть не сошел с ума, пытаясь понять, где сбой в питании, проведенном через фальш-пол. Вдруг мы услышали голос из соседней комнаты: О-ля-ля! Ты вылила всю мою бутылку воды на розетку!.

Мы побежали туда и увидели розетку, залитую лужей воды

Хорхе Б.



Лет 10-25 назад я работал в поддержке у провайдера, в какой-то момент мне позвонила женщина, которая сразу призналась, что не умеет обращаться с компьютером, но ей очень надо запустить одну программу. Она жила всего в паре минут от меня, и я решил просто зайти к ней домой.
Придя на место, я сказал, что сначала ей надо открыть меню Пуск. Она спросила меня: Что такое Меню Пуск? Постепенно я ей все объяснил и нашел приложение, которое ей было нужно. Когда я собрался уходить, она сказала, что знает еще одного человека, которому я могу помочь. Оказалось, что у нее есть маленькая дочь, и та слышала, что можно превратить курсор мыши в динозавра. Это было просто, я всего лишь поменял тему курсора Windows XP, но девочка была счастлива.

Вернувшись в офис я заполнил тикет: Помог пользователю найти приложение Х и превратил курсор мыши в динозавра.

Энди С.



Помню, у меня на работе жила саламандра в аквариуме, которая все время умудрялась вылезать из него, хотя крышка была закрыта. Однажды, она вылезла, когда никого не было, и пропала.
Через некоторое время мой компьютер отказался запускаться из-за проблем с блоком питания. Когда я открыл корпус, то увидел палочку, застрявшую в вентиляторе.
Только это была не палочка!..

Роб Х.

У нас был клиент, который прислал нам фотографию своего треснувшего экрана
сделанную с помощью Print Screen.

Лим Р.



Когда я работал в техподдержке, я, было, уделено помогал одному пожилому человеку. Когда мы со всем разобрались, я попросил его закрыть все окна, чтобы мы могли повторить все сначала. Он сказал Хорошо, скоро вернусь. Через десять минут он снова подошел к телефону и сказал: Ну, я закрыл все окна, и что теперь?
Райан Г.



Однажды я отошел от рабочего компьютера, оставив его включенным и не заблокировав заставкой с паролем. Никогда этого не требовалось, потому что коллектив был меньше десяти человек, все работали вместе несколько лет и довольно хорошо друг друга знали. Вернувшись, я увидел, что в моей аське мигает почти весь контакт лист, все мне что-то пишут, включая тех, с кем мы общались очень редко и даже не каждый месяц.

Оказалось, почему-то именно в тот день одному коллеге ударило в голову неизвестное вещество, и он решил пошутить, сев за мой кмоп и написав в мою аську: Я тряс башкой и мой хаер застрял в клавиатуре, а потом одной кнопкой разослав это по всем моим контактам (спасибо Аське, тогда это можно было сделать буквально в один клик).

Я пережил несколько неприятных минут, объясняя, что это глупая шутка коллеги. Но с ним больше не здоровался А компьютер блокировал.

Константин В.



Был случай, когда к нам в офис устроился сотрудник, который, как бы сказать поделикатнее, пренебрегал личной гигиеной. Всех достало его амбрэ, но сказать прямо стеснялись. В итоге, решили проблему довольно замороченным способом, но зато по-админски.

На компьютере Макинтош можно сбросить пароль root-пользователя с помощью специальной опции на установочном диске. Мы загрузили его Мак с этого диска, сбросили пароль root, завели еще одного пользователя и задали ему известный нам пароль. Потом зашли под root, открыли файл с хешем пароля того сотрудника, скопировали его в отдельный файл, а на его место вставили хеш пароля нового пользователя. Это позволило нам зайти в учетную запись пахучего сотрудника, использовав пароль временного пользователя. Мы поменяли на десктопе фон, поставив картинку с младенцем и большой надписью: Даже малые дети знают, что надо принимать душ каждое утро и пользоваться дезодорантом!.

После этого снова зашли под root, скопировали обратно хеш его пароля из сохраненного файла и вставили его обратно, а временного пользователя удалили.

На следующее утро мы с предвкушением ждали его реакции и были вознаграждены громким возгласом изумления, раздавшимся тогда, когда он загрузил свой компьютер. Наши старания были не напрасны, парень стал принимать душ и пользоваться антиперспирантом!

Константин В.



Несколько лет назад, работая в Лаборатории искусственного интеллекта МТИ (на самом деле очень много, потому что описывается компьютер из 60-х годов), я рылся в шкафах, где находился мейнфрейм PDP-10, и заметил маленький переключатель, приделанный к раме одного шкафа. Очевидно, это был прикол, который добавил один из местных хакеров.

На самом деле, есть правило: Не трогать переключатель, если вы не знаете, что он делает, потому что это может привести к сбою компьютера. Но этот был маркирован совершенно дурацким образом, у него было два положения, и на металлическом корпусе карандашом были нацарапаны слова магия и больше магии. Тогда тумблер был в более волшебном положении.

Я позвал другого сотрудника, чтобы он посмотрел на это чудо. Но он тоже никогда раньше не замечал его. При более внимательном изучении выяснилось, что к выключателю подведен только один провод, который скрывался в лабиринте внутри компьютера. Логично, что выключатель не может ничего делать, если к нему не подключены провода с двух сторон, но у этого переключателя был только один провод.

Понятно, что этот переключатель мог быть только чьей-то глупой шуткой. Убедившись в том, что он не должен работать, мы щелкнули им. Компьютер моментально сломался

Представьте себе наше крайнее изумление! Мы списали это на совпадение, но тем не менее вернули переключатель в более волшебное положение перед тем, как запустить компьютер снова, и больше его не трогали.

Год спустя я рассказал эту историю еще одному хакеру, Дэвиду Муну. Он посмеялся надо мной и выразил сомнения в моем здравом уме, обвинив меня, в вере в сверхъестественную силу этого переключателя. В доказательство своих слов я показал ему этот волшебный выключатель, все еще привинченный к корпусу шкафа с подключенным к нему только одним проводом, оставленный в положении больше магии. Мы внимательно изучили переключатель и обнаружили, что другой конец провода был подключен к контакту заземления. Это явно выглядело вдвойне бесполезным, он не только не работал электрически, но и был подключен к контакту, который, в любом случае, ни на что не мог повлиять. Итак, мы щелкнули выключателем.

Компьютер снова сломался

На этот раз мы побежали за Ричардом Гринблаттом, бывалым хакером из Массачусетского технологического института, который работал неподалеку. Он никогда раньше не замечал этого выключателя, но когда осмотрел его, тоже пришел к выводу, что он бесполезен, и решительно откусил провод. Затем мы перезапустили компьютер, и с тех пор он работал без проблем

Мы до сих пор не знаем, как выключатель ломал машину. Существует теория, что цепь рядом с выводом заземления была на пределе, и щелчок переключателя изменял электрическую емкость достаточно для того, чтобы нарушить цепь, когда через нее проходили импульсы с длинной в миллионные доли секунды.

Этот выключатель все еще валяется у меня в подвале. Возможно это глупо, но я держу его в положении большей магии.

Добавлено в 1994 году.

С тех пор было предложено еще одно объяснение этой истории.

Корпус переключателя был металлическим, а неподключенная сторона переключателя была привинчена к корпусу компьютерного шкафа (обычно корпус подключается к отдельной клемме заземления, но бывают исключения). Таким образом корпус выключателя был соединен с корпусом компьютера, который, предположительно, тоже заземлен. Заземление цепи внутри машины не обязательно имеет тот же потенциал, что и заземление корпуса, поэтому щелчок переключателя соединяет заземление цепей компьютера с землей корпуса, вызывая падение/скачок напряжения, которое перезагружает машину. Вероятно, это было обнаружено кем-то, кто на собственном горьком опыте, выяснил, что между ними существует разность потенциалов, а затем приделал переключатель в качестве шутки.

Хакерский фольклор МТИ



В одной конторе, где я в свое время работал, был один товарищ.

Трубку домофона в той конторе повесили у двери, к двери он сидел ближе всех, но бегать на каждый звонок ему было лениво.

Как он решил эту проблему? Он подключил контакты кнопки домофона, открывающей дверь через реле к флоппи-дисководу, расшарил доступ к диску A:, вывел всем ярлычки Открыть дверь.
После этого любой работник мог открыть дверь по локальной сети.

Фольклор

В одном закрытом военном НИИ проводили инвентаризацию и наткнулись на описание оборудования, которое никто не мог опознать. В Книге учета оно было записано как соком 50 хэ. Раз оборудование стоит на учете, его надо найти и проверить, тем более, что оценено оно было в заметную сумму условных единиц. Народ долго ломал голову, пока одному научному сотруднику не пришло в голову простое решение этого ребуса. Учетом занималась весьма пожилая женщина, без высшего образования, не знающая никаких языков, кроме русского. Потому, привод для CD-ROM, 50-скоростной, она записала как поняла, то есть соком 50 хэ.

Константин В.

Однажды, когда я работал в одной небольшой фирме, в нашем кабинете стали проводить инвентаризацию и всех попросили выйти, потому что нужно было наклеить инвентарные номера на всю мебель и оборудование, а мы им мешали. Мы решили совместить приятное с полезным и пошли обедать.

Вернувшись с обеда, мы обнаружили, что ни одна мышка не работает. Причина стала очевидна, когда я перевернул свою кверху брюшком. Ну куда еще можно наклеить инвентарный номер на мышь? Конечно же поперек отверстия с шариком!

Константин В.

В одной компании был МФУ Xerox, и у данного устройства существовала полезная особенность умение отсылать отсканированные документы на емейл. Для этого ему, как ни странно, нужна учетная запись на почтовом сервере, ибо отсылает он по SMTP. Меняли почтовый сервер, часть учетных записей мигрировали, а часть решили просто пересоздать. В процессе создания новой учетки для МФУ полезли на старый сервер уточнить login и обратили внимание на папку с входящими письмами. С сервера адский агрегат почту не забирал, так что скопилось ее порядка пятидесяти мегабайт.

Оказалось, что народ ведет активную переписку с МФУ, пишет ему Спасибо! и Благодарю за документы!. Особенно запомнилось сообщение одной сотрудницы: Спасибо, скан договора получила, жду от Вас приложение 2

Фольклор

Был случай, когда студентам, изучающим искусственный интеллект, дали задание написать самообучающегося бота для 3д-шутера. Студенты справились с заданием и запустили ботов в локалку, чтобы они за ночь наловчились убивать друг друга. Утром зашли в сетку и стали тестировать своих ботов. Выяснилось, что живых игроков выносят в первые же секунды, и выжить нет ни единого шанса. Когда стали смотреть логи, оказалось, что уровни в игре были сделаны небрежно, между текстурами были зазоры, которые не бросались в глаза игрокам, но были обнаружены ботами, и позволяли им прятаться внутри стен, проходя в любое помещение и убивать игроков, не давая им обнаружить себя.

Фольклор



Друг работает на складе комплектующих для компьютера.

Им пришёл заказ из СНБ на 100 модулей оперативной памяти. Вы представляете себе сто оперативок? Упаковали их компактно в коробочку 60 на 40 сантиметров. Приезжает представитель СНБ, у них с менеджером происходит диалог, после которого менеджер вползает в конвульсиях в кабинет шефа, вручает ему коробку с памятью и просит выйти самого.

Шеф выходит на крыльцо. Там стоит вышеупомянутый представитель, который показывает на КАМАЗ С ПРИЦЕПОМ!.. и выдаёт: Я тут машину подогнал, если этого не хватит, то мы ДВЕ ХОДКИ СДЕЛАЕМ!..

Шеф не растерялся, протягивает представителю коробочку и просит подержать. Сам подписывает документы, стоит и улыбается. Представитель начинает нервничать: Где же товар, у меня люди ждут, ЗАГРУЖАТЬ НАДО!.

Шеф: Он у вас в руке.

Фольклор



Мой брат живет в соседнем штате и уже достал просьбами помочь ему с компьютером по принципу тыжпрограммист. Некоторые из звонков в семейную службу техподдержки были болезненные как лечение у стоматолога. Ему казалось, что в его компьютер попадают вирусы и трояны, после чего он звонил мне. Он мог часами держать меня на телефоне, заставляя чинить ему компьютер.

Однажды я решил эту проблему раз и навсегда.

Тебе надо зайти в Гугл
Как мне это сделать?
Откройте свой браузер, введите Google и нажмите Enter.
Что за браузер? Как я могу это сделать?
Это, с чего ты смотришь что-либо в Интернете
О Он только что открыл Word? Так и надо было?

И в таком духе разговор продолжается больше часа. Внезапно мне в голову приходит дикая идея. Последовательно я подвожу его к тому, чтобы загрузить и установить VNC. Затем заставляю его посетить несколько сайтов по компьютерной безопасности, чтобы напугать его последствиями беспечного поведения в интернете, все время читая лекции на эту тему.

Я: Интернет действительно опасное место. Ты должен быть осторожен. Очень осторожен. Есть хакеры, которые хотят взломать твой компьютер. Если они заразят твой компьютер, то загрузят на него хакерские программы, которые будут делать всякие неприятные вещи. Они могут украсть твои пароли или получить доступ к банку и кредитным картам!

Одновременно с этим я через VNC случайно открываю и закрываю окна, захожу на разные сайты.

Я: Они даже могут захватить твой компьютер, превратив его в бота, которым ОНИ будут управлять. Я слышал рассказы о людях, к которым приходили из ФБР, потому что их компьютер был захвачен хакерами, и использовался для атак на Белый дом или Пентагон. Бедные люди даже не был в курсе, что их взломали

При этом я открываю и закрываю все больше окон.

Он: Эй! Я не уверен, что происходит, но мой компьютер ведет себя странно. Он пытается самостоятельно выйти в Интернет!
Я: Ой-ой. Это плохо! Ты уверен, что печатаешь не слишком быстро? На всякий случай запусти антивирус. Если ты не сможешь этого сделать, то это очень плохо.

Он пытается, но я мешаю движению его мыши. Наконец я позволил ему запустить программу, и как только она открылась, то я сразу закрыл ее.

Он: Я начинаю волноваться. Я не знаю, что происходит! Я ничего не могу сделать на своем компьютере!!!

А я открываю командную строку и запускаю команды: IPCONFIG, netstat, tracert whitehouse.gov и тд.

Я: Вау что ты сделал?! Выглядит очень серьезно. Похоже, твой компьютер был атакован Может быть, хакер пытается проникнуть в него. Возможно, тебе придется отключить его. Похоже, они пытаются добраться до твоего банка или того хуже

При этом начинаю набирать:

Access: Pentagon Classification TS5
PASSWORD REQUIRED: ******
FAILURE 1 NOTED: Alert sequence
Delta Alpha Charlie initiated : IP TRACKING LEVEL 1 PRIORITY INITIATED
WARNING - PASSWORD FAILURE 2
ALERT TEAM NOTIFIED: FINAL PASSWORD FAILURE
Security Breach detected. Tracking completed. IP ADDRESS confirmed. Response Team dispatched. Address Confirmed: Illegal security breach confirmed. Trace complete. Team dispatched - 2123 Main street: Perpetrator confirmation - John Smith.


Естественно, я использовал его реальный домашний адрес.

Я продолжал пугать его, набирая вышеуказанное, но он начал меня перебивать

Ой, чувак, это действительно очень плохо Они взламывают Пентагон. Что мне делать. Что делать?!

Я намереваясь действовать слишком медленно для его удобства.

Ой, ты должен запустить антивирус.
ПОМОГИТЕ! Они знают, кто я. Что мне делать?!
Ну, я бы посоветовал выключить компьютер, положить его в коробку и вернуть в магазин!
Наконец я уже не смог сдерживать смех и спалился, а потом объяснил ему, что я делал. Почему-то это не показалось ему настолько смешным, как мне. Но с тех пор мне не звонили как тыжпрограммисту!

Комментарий к статье



Наверное, худшая история, которую я могу вспомнить, помимо обычной головной боли от пользователей, была о том, как мне пришлось провести исследования активности одного пользователя в сети. Было показано, что этот человек генерирует очень большой трафик во второй половине дня и замедляет работу всего отдела. После нескольких минут изучения логов я обратил внимание на название одного из его часто посещаемых сайтов. Уже не помню конкретный адрес, но то был сайт, посвященный КРУПНМ женщинам. Я передал эту информацию своему руководителю, который передал ее дальше, и скоро я получил ответ от начальника моего босса, что им нужны конкретные примеры того, на какие типы сайтов он заходит, со скриншотами.

Остаток дня я никогда не забуду Если бы у меня под руками был отбеливатель, я бы залил его в свои глаз сразу, как только он зашел на тот сайт. Очевидно, этот джентльмен проводил 80% своего времени, просматривая очень сомнительные материалы в офисе.

После сбора снимков экрана в течении двух часов я связался с начальником моего босса, чтобы показать ему свое расследование

Позже он сказал мне, что они поговорили с тем сотрудником, и он уволился.

110 != 220

Это был мой первый год в ИТ, и мне пришлось менять компьютер, который управлял огромной сушилкой для древесины. Мне не очень много лет, но тогда многие компьютеры работали под DOS.

Я позвонил в Германию, в компанию по производству печей, нашел человека, который владел английским, получил спецификации, собрал снаряжение и уехал к заказчику, который находился за 200 миль. После резервного копирования предыдущей системы (на дискеты!) я вытащил огромную сетевую карту из старого компьютера, вставил в новый, подключил питание к ИБП и нажал кнопку включения.

БУМ

Голубой дымок из перегоревшего блока питания С побелевшим лицом я позвонил начальнику, рассказал ему обо всем, что я сделал, и к чему это привело.

Не переживай, щит хепенс, просто зайди в компьютерный магазин в получасе езды, купи новый блок питания и попробуй еще раз. Да, и удали эту чудовищную сетевую карту, прежде чем снова включишь питание!.

Быстро съездив до магазина и обратно, я возвращаюсь с новым блоком питания, заменяю его, снимаю сетевую карту и снова нажимаю кнопку питания.

БУМ

Еще больше голубого дыма, и мое лицо побелело еще сильнее. Я перезваниваю своему боссу: Опять что-то не так с вашей установкой. Через несколько минут, обсудив с ним все по телефону, мы пришли к выводу, что компьютер собран правильно, а проблема в чем-то другом.

Куда ты подключил шнур питания?
К ИБП
Хммм А чьего он производства? Ты не знаешь? Написано по-немецки?
Да
Тогда вернись в магазин, купи новый блок питания и поставь красный переключатель на задней панели на 220В. Перезвоните мне, когда печь снова заработает.

Вот так выяснилось, что в Германии техника работает на 220В. Думаю, 19-летний парень из Канады, которым я тогда был, мог этого не знать.

Из комментариев к статье



Когда я только начинал свою карьеру в сфере IT, и мне сказали, что один VIP-пользователь никак не может подключиться к VPN, попросили помочь. На его рабочем компьютере все было в порядке, поэтому я попросил пользователя лично показать мне, что он делает. Он достал свой токен RSA, ввел код с него и вошел в систему.

Однако этот пользователь не первый раз жаловался эту проблему, и я был не первым, кто пытался ему помочь. Я попросил его рассказать по шагам, что он делает перед тем, как у него не получается зайти в сеть.

Сначала, я достаю свой ноутбук, подключаю сетевой кабель, подключаюсь к Интернету из дома. Потом запускаю VPN-клиент, вытаскиваю этот листок с кодом и набираю его

Оказалось, что он записывал код с токена RSA перед тем, как уйти домой, а сам токен оставлял на работе, потому что эта штука была довольно дорогой, и он не хотел ее терять. Я объяснил, что номер все время меняется, и ему нужно всегда носить его с собой. Проблема с VPN была решена.

Комментарий к статье

Одна из компаний, поддержкой которых мы занимались на моей прошлой работе, была университетская полиция. И вот однажды моему коллеге позвонил начальник полиции и сообщил, что что-тоне так с подключением к сети Ethernet на его новеньком ноутбуке. Мы быстро подъехали, чтобы взглянуть на его ноутбук. Проблема была очевидна!

Каким-то образом (ядо сих пор не знаю, как у него хватило силы) начальник полиции вставил кабель Ethernet в разъем модема RJ-11. И вставил его так сильно, что треснул корпус вокруг разъема.

Комментарий к статье

Несколько лет назад мне позвонил один пользователь и пожаловался, что у него проблемы с печатью на принтере в его кабинете. Я зашел в настройку Принтеры WindowsXP и увидел, что принтера там нет.

Я подошел к его столу, чтобы проверить соединение, но обнаружил, что его рабочая станция не подключена к принтеру.

Зачем мне это нужно?, он спросил, Это же ЛАЗЕРНЙ принтер!"

Комментарий к статье



Этот было середине 90-х, в старые добрые времена DOS. Я работал в очень большом банке и оказывал поддержку пользователям по всему штату. Обучение сотрудников там не одобрялось, и в бюджете не было предусмотрено, поэтому у нас были здания заполненные людьми, пытающимися понять, как заставить работать их компьютеры. Одна дама работала в налоговом отделе, лет ей было 190, и она использовала компьютер только потому, что была вынуждена (опять же без обучения!). Я настроил для нее систему и сделал ее максимально удобной для пользователя, насколько это вообще было возможно в DOS. У нее было простое меню с тремя вариантами, один из которых запускал налоговую программу.

Однажды она позвонила мне очень сильно раздраженная: На моем экране ничего нет!. Не имея в своем распоряжении никаких диагностических инструментов, кроме своего воображения, я начал использовать ее как свои глаза.

Посмотрите на монитор, ту штуку, которая похожа на телевизор, горит ли зеленый светодиод?
НЕ ЗНАЮ
Посмотрите справа от телевизора, 2 дюйма вниз и 1 дюйм направо.
Есть зеленая лампочка.

Я еле удержался от комментариев, и мы повторили этот процесс для компьютера, с аналогичными сложностями в переводе с айтишного языка на понятный ей. После выяснения того, что все действительно было включено и работало правильно, я снова обратил внимание на монитор. Мог ли он сгореть?

Хорошо, я хочу, чтобы вы посмотрели в телевизор. Вы видите что-нибудь похожее на светящиеся оранжево-желтые буквы где-нибудь на стеклянной части телевизора?
О да, там написано 'C: ->'

Я подумал объяснить ей, что она смотрела на приглашение DOS, но решил пропустить такие подробности.

Наберите MENU, нажмите Enter и расскажите мне, что происходит
Ничего.
Есть новые яркие символы?
Да: Bad command or filename C:->.

Несколько попыток запустить приложение Menu не увенчались успехом, поэтому я подумал, что, возможно, приложение было повреждено. После внутренних стенаний о том, что будет дальше, я сказал:

Давайте попробуем запустить приложение Tax без меню. Я хочу, чтобы вы набрали: CD (space) TAX, нажмите Enter и расскажите мне, что произошло.
Ничего! На экране ничего нет!

С растущим возбуждением я прошу:

ПОСМОТРИТЕ НА 1/2 дюйма от того места, где остановились ваши глаза и прочтите чертовы светящиеся символы!
Bad command or file name".

Я был в недоумении Потом еще подумал несколько минут, и мне в голову пришла идея.

Прочитайте по буквам то, что вы только что набрали
S E E D E E S P A C E T A X"

Именно в тот момент своей карьеры я понял, для чего на самом деле нужна кнопка отключения звука. Когда я отключил свой телефон, то с криком ударился головой об стол!

Комментарий к статье



У меня было много такого, чего я уже не вспомню, но есть один случай, когда одна девушка сообщила: На мониторе моего компьютера утка.

Служба поддержки 1-го уровня удаленно проверила ее машину и не нашла вредоносных программ или приложений, которые могли бы вызывать такое поведение. Они уже собирались прислать мне компьютер, чтобы я физически проверил, но, прежде чем отдать мне свою машину, она заявила, что со всем разобралась.

Мне было очень любопытно, что же вызвало такую проблему, поэтому я спросил, что произошло

Она ответила, что вентилятор наклеил на ее монитор стикер с уткой, и она просто не заметила этого.

Комментарий к статье

Однажды вечером нам позвонили из небольшой фирмы примерно в 70 милях от нас. Перед этим мы продали им новый принтер, все, что им нужно было сделать установить драйверы и подключить устройство. Ничего особенного.

Но они позвонили мне и сказали, что компакт-диск не помещается в дисковод. Читая наклейку на диске, они сказали, что поняли проблему. На диске было написано, что он предназначен для MAC, а мне нужно было отправить им диск для Windows, так как компакт-диск от MAC не влезет в привод. Дело было срочное и я поехал к ним в офис.

Я понял проблему сразу, как только вошел в офис, потому что на верхней части компьютера были маленькие резиновые ножки. Решение? Переверните компьютер и теперь CD отлично подходит!

Комментарий к статье

Было дело, в техподдержку позвонила женщина позвонила и сказала, что каждый день она сохраняет свою базу данных на дискете, а на следующий день дискета всегда пуста.

После того, как несколько дней мы просили ее проверять целостность данных в резервной копии, и все было в порядке, но на следующий день снова все исчезало, мы отправили к ней технического специалиста.

Что он увидел?

После сохранения данных на диск 5 1/2 она прикрепляла его к своему металлическому шкафу с помощью промышленного магнита.

Комментарий к статье



В один момент мне было необходимо срочно проложить четыре десятка проводов витой пары на расстояние в сто метров. Большая часть дистанции проходила над навесным потолком на трёхметровой высоте. Поняв, что для моих единственных в конторе админских плеч решение задачи в приемлемые сроки является непосильным, я принялся терзать шефа на предмет привлечения сторонних монтажников, и тот, скрепя сердце, согласился. Я разработал техзадание, разослал по разным конторам и стал ждать.

Одно из предложений сильно выделялось из общей массы. Ребята утверждали, что работу они выполнят всего за один день, причём втрое дешевле, чем любой из конкурентов! На всякий случай перезвонил и уточнил, правильно ли они поняли задание. Ответили, что поняли прекрасно, а скорость и дешевизна объясняется тем, что в работе используется кабелеукладчик. Я был заинтригован. С кабелеукладчиками имел дело в армии и решительно не представлял, каким образом данный девайс можно приспособить к прокладке витой пары под фальшпотолком.

В назначенный день прибыли всего два монтажника со стремянками и инструментами. Наблюдая за процессом разгрузки, я с нетерпением ждал чудо-агрегата, способного автоматизировать процесс. Агрегата так не дождался, зато последней из микроавтобуса была выгружена некрупная такса. Не успел я удивиться по поводу появления животного, как мне объяснили, что это и есть таинственный кабелеукладчик.

В комплекте к таксе шел специальный костюмчик с ручкой вдоль спины для переноски, сбруя на голову со светодиодным фонариком и шлейка. Прокладка кабеля осуществлялась путём прикрепления его к шлейке и запуска таксы в труднодоступное место. Надрессированное животное шустро мчалось на звук голоса или свет фонаря, волоча за собой провод. Потолок собаку выдерживал, мощности же хватало метров на пятьдесят.

Скорость прокладки в длинных и труднодоступных участках была просто фантастической. Такса резво носилась в одну сторону по верху, а обратно по коридору, пугая женскую часть персонала. Даже ЧП в виде выпавшей панельки потолка не повлияло на её настроение: протягиваемый провод сыграл роль страховочного троса, и собачка плавно опустилась на пол. Ребята сказали, что к таким ситуациям кабелеукладчик приучен.

Смех смехом, но такса на полном серьёзе стояла у ребят на балансе фирм. Мне были продемонстрированы документы. Работу дружный коллектив действительно выполнил менее, чем за день, причем без предварительного разматывания кабеля и, соответственно, без обрезков. Правда, работа нашей конторы полностью встала: всё население сбежалось посмотреть за работой кабелеукладчика.

Фольклор

Мы поставили пиво в холодильник и ждем ваших историй


Победителя определим через неделю, 10 марта.

Напоминаем правила:

  • Ваша любимая история, личная, рассказанная другом за бутылочкой пива, прочитанная когда-то
  • Баночка за каждую историю
  • Ящик эля за самую заплюсованный историю в комментариях


Подробнее..

Как получить работу мечты благодаря смертельному диагнозу

05.08.2020 06:20:04 | Автор: admin
В этой истории, как и положено, всё кончилось хорошо, но позвольте до конца сохранить интригу.
Ранее я уже писал про свой опыт работы в Южной Америке, однако за кадром осталось множество весёлых и не очень историй, связанных с разработкой, вертолётами, наркомафией, да и чисто бытовых вещей, с которыми сталкиваешься ежедневно. Коллеги любят слушать эти байки и подбили изложить наиболее интересные здесь.


Начну сначала. Итак, меня пригласили на работу в Колумбию, но ценна тут не сама страна, а проекты, которыми предстояло заниматься. Вишенкой был проект стенда испытаний вертолётных двигателей ТВ3-117, который предстояло построить практически с нуля. Вся моя жизнь была связана с авиацией и БПЛА, а тут такой проект идёт прямо в руки!


Так выглядит стенд сейчас

К тому моменту мы уже пять лет успешно делили жилплощадь с моей будущей женой, но давать ей визу как девушке консульство категорически отказалось, чем она умело и воспользовалась. На брак было всего 2 недели и пришлось потрудиться, чтобы нас расписали без положенного месяца на обдумывание. Особенно чудовищным для работников ЗАГСа казалось то, что мы не хотели бурной свадьбы с осыпанием рисом и голубями, а хотели распишите нас и мы пойдём. В итоге, в ЗАГС мы входили через заднюю дверь. Отсидев очередь среди рецидивистов бракоразводного дела, имевших за спиной уже по 2-3 ходки, мы таки получили возможность поставить заветные подписи. Всего через два дня я отбыл менять мир, а жена фамилию.

К моему приезду уже стояла коробка помещения стенда, металлический постамент двигателя и были проложены кабель-каналы. Рядом валялось несколько бухт кабелей и коробка с блоками ADAM, купленных по образцу аналогичного проекта. Нужно было всё собрать, отладить, переписать сделанный под Delphi-5 исходник и добавить необходимые функции. Количество предстоящих hardware багов невозможно было даже оценить.
На всё давалось 4 месяца.
Параллельно нужно было заняться оформлением документов на рабочую визу. Среди прочего, нужно было сдать анализы на ВИЧ и гепатиты В/С.
В Колумбии страховая медицина, поэтому, если у тебя нет медстраховки, помочь тебе могут только врачи частной практики. Компании (да и физлица) выбирают варианты подешевле, поэтому обычное явление, когда врач, лаборатория и аптека, где могут выдать рецептурные препараты, находятся в трёх разных концах города, причём, где-то между борделем и мясной лавкой.
Так вышло и у меня врач сидел на Юге, направление было выписано в лабораторию на Севере города. Повторный приём не предполагался. Следующим утром я явился в лабу, где на ломаном английском (испанского я тогда не понимал) девочка на приёме объяснила, что точно такой анализ, как написал врач, они сделать не могут, но могут аналогичный. На мой вопрос он же тоже на гепатит? девочка утвердительно кивнула. Ну не такой так не такой, какая мне разница? Деньги уплОчены, кровь откачана, едем домой.
Анализы такого уровня отдают только лично в руки по документу, причём запечатаны они в конверт. Пришлось ехать снова. Забрал конверт, вышел на лавочку, распечатываю и оп-па Жирная красная строка.

В первый момент я даже не понял какой из трёх вирусов найден. Зрение работало, но мозг отказывался воспринимать информацию. Спустя немного времени я смог прочитать, что красным отмечен гепатит В.

Теперь вы поняли, почему я так подробно рассказал предысторию женитьбы? На тот момент нашему браку было меньше месяца. Кто конкретно источник заразы и как давно она у нас было не важно (а то, что у нас обоих, сомнений не было, гепатит В очень заразен). Важно, что это совершенно иной статус и качество будущей жизни. Ну и перспектива получить визу и работу ушла в туманную даль
С такими думами я пришёл к своему начальнику на следующий день. Тот был шокирован не меньше моего. Решили, что я сделаю по проекту максимум возможного, а они заплатят премию, ведь деньги тебе понадобятся.
Также меня отвели к корпоративному медику, а тот отвёз меня в госпиталь, где мне выдали антиретровирусную терапию. Это 3 препарата в безликих белых банках со штрихкодом вместо названия и красной лентой на крышке символом ВИЧ инфекции. Два препарата пьются утром и днём, и все три на ночь. Сшибает с них как со стакана водки. Гул в ушах, головокружение, апатия, отсутствие аппетита, депрессивное состояние всё это прилагается бесплатным бонусом. Ну и осознание, что ты теперь с этим на всю жизнь
Также медик выбил мне приём у врача, назначавшего анализы, но свободное место было у него только через 3 (три [ТРИ!!!]) недели. Жене решил не говорить до приёма.
Чтобы как-то отвлечься от грустных мыслей, я начал пахать. Когда работаешь, грустить некогда. На работе тянул и распаивал кабели, монтировал коробки, датчики и системы. Есть особо не хотелось, поэтому в обед тоже работал. С работы уезжал вторым рейсом (корпоративные автобусы ходили в 17 и 20 часов). Дома правил код на личном ноутбуке. Закинувшись колёсами из безликих банок, спал. И так сначала. Repeat until KeyPressed;

В общем, то, на что давалось 4 месяца, я запустил за 4 недели. К моменту повторного визита к врачу двигатель на стенде уже делал холодную прокрутку, а измерительная часть полностью функционировала.

К врачу со мной поехали корпоративный медик и переводчик, знавшие мою грустную историю. Надо отметить, что хотя колумбийцы и раздолбаи на генетическом уровне, но люди очень участливые и сочувствующие.
Врач выслушал мой рассказ, включая смену типа анализа, ещё раз (как и в первый приём) уточнил, была ли ранее сделана прививка от гепатита В. Получив утвердительный ответ врач произнёс ранее неизвестный мне медицинский термин hija de puta и, уже через переводчика, объяснил, что мне сменили ПЦР анализ, определяющий ДНК вируса в крови, на анализ на антитела к вирусу, которые у меня, как у привитого, конечно же, были.

Тут и сказочке конец. ПЦР анализ вышел зелёным, а момент, когда я выкидывал безликие банки в мусорный бак один из самых счастливых в моей жизни.

Случилось это в канун католического Рождества, 23 декабря 2010 года, а на 28 декабря мне был куплен обратный билет домой. Испытательный срок закончился досрочно, а в получении контракта не было сомнений такой ядерной работоспособности в компании никто ранее не встречал. Да и преград для рабочей визы теперь не было.

В Колумбию мы вернулись в феврале и подобных случаев, связанных с колумбийской инициативой, впереди было ещё много, но это уже совсем другая история :)

Подробнее..

Перевод Обратная сторона Open Source-славы как угрожают автору curl

23.02.2021 14:15:47 | Автор: admin

Прим. перев.: уникальная история, что всколыхнула интернет в эти дни, показывает неожиданную сторону того, что могут заслужить авторы самых популярных Open Source-проектов. Ниже представлен перевод недавней заметки из блога шведского программиста Daniel Stenberg оригинального автора и главного разработчика curl, обладателя премии Polhem Prize (вручается в Швеции за выдающиеся инженерные достижения).

Как вам, наверное, известно, в своем блоге я публикую забавные электронные письма, которые периодически приходят мне на адрес. Ну, знаете, когда мне пишут о проблемах с каким-то своим устройством (вроде автомобиля), потому что мой email где-то там засветился.

Мне иногда советуют завести новый адрес или указать другой в файле лицензии к curl, но, откровенно говоря, все эти странные письма ни разу не доставляли проблем, а лишь служили очередным напоминанием о непростых вызовах, которые ставит перед людьми современная жизнь, зацикленная на технологиях. Ну и, конечно, всегда забавно узнавать, где еще можно встретить curl.

Увы, не все эти письма забавны.

Категория: не смешно

Сегодня я получил следующее письмо:

От: Al Nocai <[скрыто]@icloud.com>

Дата: Пт, 19 Фев 2021 03:02:24 -0600

Тема: Я тебя убью

Да, именно такая тема (I will slaughter you).

Более 20 лет являясь мейнтейнером ПО с открытым исходным кодом, я прекрасно осведомлен о флейм-войнах и персональных выпадах. Благо, у меня довольно толстая кожа и словам нелегко меня уколоть. Минута ушла на то, чтобы все осмыслить и понять, что это прямая угроза физической расправой. И предназначается она именно мне. Откровенно говоря, к такому уровню агрессии я оказался не готов.

К письму были приложены семь изображений без каких-либо пояснений. Изображения выглядели как скриншоты с телефона, и на первом виднелся написанный мной код и строка с копирайтом:

На других скриншотах также был исходный код и связанная с ним информация о сборке/программном обеспечении других компонентов, но я не смог определить, какое отношение они имеют ко мне.

Никаких объяснений; только тема и семь изображений, поэтому мне оставалось только догадываться о цели этого послания.

Я решил, что имя в письме выдуманное, а адрес электронной почты, скорее всего, одноразовый. Часовой пояс в строке с датой намекал на Центральное стандартное время США, но, конечно, мог быть подделкой, как и все остальное.

Мой ответ

Как правило, я не отвечаю на подобные письма, поскольку расстояние между мной и их авторами обычно имеет планетарный масштаб. Но на этот раз я решил, что подобное поведение совершенно неприемлемо для меня и любого приличного общества, и просто не смог оставить этот выпад без внимания. Сделав небольшую паузу и побродив по дому пару минут, чтобы остыть, я написал весьма гневный ответ и отправил его.

Это письмо совершенно и абсолютно неприемлемо, и оно глубоко ранило меня. Вам должно быть стыдно! Подумайте о том, чтобы пересмотреть свои манеры.

Я понятия не имею, что означают эти скриншоты. Вижу только, что кто-то где-то использует код, написанный мной. Этот код можно найти практически на каждом подключенном к интернету устройстве, и в большинстве случаев пользователи скачивают этот код и используют его совершенно бесплатно и не ставят меня в известность об этом.

Очевидно, что вы не достойны моего кода.

Впрочем, я не надеялся, что мой ответ будет прочитан или что-то изменит.

Примечание: Обновление ниже добавлено после первоначальной публикации.

Ответ Al Nocai

Вопреки моим ожиданиям, он ответил. Его ответ нет смысла комментировать, но я все же опубликую его здесь ради открытости.

Мне плевать. Твое дерьмовое ПО послужило вектором атаки, из-за которой я потерял многомиллионный оборонный проект.

Они использовали твое дерьмовое ПО, чтобы украсть root у меня и у многих других. Из-за этого только на прототипировании я потерял более 15 тысяч долларов.

С октября я живу в изоляции всему виной твое дерьмовое ПО, из-за которого долбаная Google-шпана может развести меня, пытаясь выманить из изоляции, поскольку они слишком бедны, чтобы представлять, что делают.

Знаешь, что я сделал, чтобы заслужить это? Я пытался разработать торговый путь в сфере технологий и разработать методики обучения на основе проектов, чтобы детки были при деле. И знаешь, кто во всех этих файлах? Ты. Это отвратительно. Меня взломали в октябре 2020, перехватив трафик федерального сервера, и всем этим я обязан тебе.

Мне пришлось сидеть и смотреть вот на это:

1. fireeye в октябре 2020;
2. Solarwinds в октябре 2020;
3. взлом модемов Zyxel в октябре 2020;
4. множество векторов атаки на Sigover с помощью XML injection;
5. стохастическая шаблонизация в JS с использованием выражений сравнения для записи в регистры данных;
6. 50-миллиардные компании охотятся за мной, поскольку я разоблачил их дерьмовое вредоносное ПО.

И меня взломали и перенаправили важную корреспонденцию в другое место. Какой-то больной ублюдок разрушил мою жизнь с помощью кода с твоим именем. Из-за этой ситуации я даже не могу уехать из страны; если уж ты смог запилить код, который гадит всем подряд, то мне совершенно наплевать на твои чувства по этому поводу.

Ты построил гоночный болид для Формулы-1, а ключи бросил шпане с раздутым эго. А теперь из-за всего этого мусора мне приходится разбираться с уязвимостями нулевого дня в Win10.

Я потерял свою семью, свою страну, своих друзей, свой дом и 6 лет работы, пытаясь построить лучшее будущее для потомков. И во всем этом виноват твой код. Этот код используется для того, чтобы похищать root и внедрять эксплойты. Этот код используется для шантажа.

Так что я ни капельки не расстроен. Ты прекрасно представлял себе возможности этого кода. И думал, что все это большая шутка. А я не смеюсь. Я уже давно прошел эту точку. /- Al

Al продолжает

Через девять часов после публикации оригинальной заметки в блоге, Al прислал мне еще два электронных письма. Вот они:

Письмо 3:

https://davidkrider.com/i-will-slaughter-you-daniel-haxx-se/

Валяй. Ты меня не испугаешь. Что привело меня сюда? 5-е покушение на мою жизнь. Условия предоставления услуг Apple? Иди к черту со своей платформой.

Забавно, что он нашел публикацию о заметке в моем блоге.

Письмо 4:

Есть проект: Анализ риска военных операций в урбанизированной местности с помощью широкополосного анализа электромагнитного спектра с использованием различных преобразований Фурье.Ты и этот David Krider, кем бы он ни был, вы часть всего этого.

- Взломы федеральных серверов;
- соучастие в покушение на убийство;
- мошенничество;
и т.д.

На данный момент я разговаривал с ФБР, региональным отделением ФБР, министерством по делам ветеранов США (VA), офисом генерального инспектора VA, Федеральной комиссией по связи (FCC), Комиссией по ценным бумагам (SEC), АНБ, Минздравом (DOH), Управлением служб общего назначения (GSA), МВД, ЦРУ, Бюро финансовой защиты потребителей (CFPB), Министерством жилищного строительства и городского развития (HUD), MS, Convercent; по состоянию на сегодня представители 22 отдельных ведомств вызванивают меня и тратят мое время.

И отвечаете за это вы с чертовым Дэйвом. Мне насрать, звони в полицию. Я их обматерю, когда они позвонят, и они заткнутся.

(Прим. перев.: в английском варианте сохранено своеобразное форматирование и опечатки.)

К письму 4 также был приложен PDF-файл с названием BustyBabes 4.pdf. Он представляет собой 13-страничный документ о NERVEBUS NERVOUS SYSTEM. Первый параграф гласит: NerveBus Nervous System призвана быть универсальной платформой для всестороннего и комплексного анализа, предоставляя конечному пользователю целостную, связную и реальную информацию о среде, которую тот мониторит. В документе не упоминается ни curl, ни мое имя.

Поскольку я ничего не знаю о статусе этого документа, не буду делиться им публично, но скриншот первой страницы приложу:

Дополнительная информация

Тема на Hacker news и Reddit.

Я сообщил об угрозе в шведскую полицию (по месту жительства).

P.S. от переводчика

В то время, как в комментариях Hacker News обсуждают, что приведенный в письме список обвинений (где упомянуты FireEye, SolarWinds и т.п.) набор бессмысленных фраз (что, возможно, указывает на психические отклонения), в комментарии к публикации в блоге Daniel Krider можно найти некоторые уточнения по этому поводу от самого автора:

I have since October, had my entire life sandboxed by individual Daniel Patrick Ehrlich to find software loopholes to aid in development of SCNR, an aggregation bot for Open Source Intelligence tied to Subverse Media and Timothy Pool, the Journalist.

I know the following:
1. React JS primary utility is to obfuscate URIs to inject malicious code
2. This code is commonly down my user agents, KHTML, primarily Favicons as they are the SVG type, and carry injectable XML.
3. Qualcom BT Adapters and drivers are routinely hacked via the SigOver attack vector through malicious sub packet injection.

P.P.S.

Читайте также в нашем блоге:

Подробнее..

Перевод Фольклор программистов и инженеров (часть 1)

18.08.2020 10:04:18 | Автор: admin


Это подборка историй из интернета о том, как у багов иногда бывают совершенно невероятные проявления. Возможно, вам тоже есть что рассказать.

Аллергия автомобиля на ванильное мороженое


История для инженеров, которые понимают, что очевидное не всегда является решением, и что насколько бы факты ни казались неправдоподобными, это всё равно факты. В подразделение Pontiac Division корпорации General Motors поступила жалоба:

Пишу вам второй раз, и не виню вас в том, что вы не отвечаете, ведь это звучит безумно. У нашей семьи есть традиция: каждый вечер после ужина есть мороженое. Сорта мороженого каждый раз меняются, и поужинав, вся семья выбирает, какое мороженое нужно купить, после чего я еду в магазин. Недавно я купил новый Pontiac, и с тех пор мои поездки за мороженым превратились в проблему. Видите ли, каждый раз, когда я покупаю ванильное мороженое и возвращаюсь из магазина, машина не заводится. Если я приношу любое другое мороженое, машина заводится без проблем. Хочу задать серьёзный вопрос, вне зависимости от того, насколько глупо это прозвучит: Что такого есть в Pontiac, из-за чего он не заводится, когда я приношу ванильное мороженое, но при этом легко заводится, если я приношу мороженое с другим вкусом?.

Как вы понимаете, президент подразделения отнёсся к письму скептически. Однако на всякий случай отправил инженера проверить. Тот был удивлён, что его встретил обеспеченный, хорошо образованный мужчина, живущий в прекрасном районе. Они договорились встретиться сразу после ужина, чтобы вдвоём съездить в магазин за мороженым. В тот вечер было ванильное, и когда они вернулись в машину, та не завелась.

Инженер приезжал ещё три вечера. В первый раз мороженое было шоколадным. Машина завелась. Во второй раз было клубничное мороженое. Машина завелась. На третий вечер он попросил взять ванильное. Машина не завелась.

Здраво рассудив, инженер отказался верить в аллергию автомобиля на ванильное мороженое. Поэтому договорился с владельцем машины, что он продолжит свои визиты, пока не найдёт решения проблемы. И попутно начал делать заметки: записывал всю информацию, время суток, сорт бензина, время приезда и возвращения из магазина, и т.д.

Вскоре инженер догадался: владелец машины тратил на покупку ванильного мороженого меньше времени. Причина была в раскладке товара в магазине. Ванильное мороженое было самым популярным и лежало в отдельном морозильнике в передней части магазина, чтобы его было легче найти. А все остальные сорта находились в задней части магазина, и на поиск нужного сорта и оплату уходило значительно больше времени.

Теперь вопрос был к инженеру: почему машина не заводилась, если с того момента, когда заглушили двигатель, проходило меньше времени? Поскольку проблемой стало время, а не ванильное мороженое, инженер быстро нашёл ответ: дело было в газовой пробке. Она возникала каждый вечер, но когда владелец машины тратил на поиск мороженого больше времени, двигатель успевал достаточно охладиться и спокойно заводился. А когда мужчина покупал мороженое, двигатель ещё оставался слишком горячим и газовая пробка не успевала рассосаться.

Мораль: даже совершенно безумные проблемы иногда бывают реальными.

Crash Bandicoot


Переживать такое болезненно. Как программист, ты привыкаешь обвинять свой код в первую очередь, во вторую, в третью и где-то в десятитысячную очередь обвиняешь компилятор. И ещё ниже по списку уже обвиняешь оборудование.

Вот моя история о баге железа.

Для игры Crash Bandicoot я написал код для загрузки и сохранения на карту памяти. Для такого самодовольного разработчика игр это было словно прогуляться по парку: я считал, что работа займёт несколько дней. Однако в результате отлаживал код шесть недель. Попутно я решал и другие задачи, но каждые несколько дней на несколько часов возвращался к этому коду. Это была агония.

Симптом выглядел так: когда сохраняешь текущее прохождение игры и обращаешься к карте памяти, почти всегда всё проходит нормально Но иногда операция чтения или записи завершается по таймауту без какой-либо очевидной причины. Короткая запись зачастую повреждает карту памяти. Когда игрок пытается сохраниться, он не только не сохраняется, но ещё и рушит карту. Блин.

Спустя некоторое время наш продюсер в Sony, Конни Бус, начала паниковать. Мы не могли отгрузить игру с таким багом, и спустя шесть недель я не понимал, в чём причина этой проблемы. Через Конни мы связались с другими разработчиками PS1: кто-нибудь сталкивался с подобным? Нет. Ни у кого не было проблем с картой памяти.

Когда у тебя нет идей по отладке, то практически единственным подходом остаётся разделять и властвовать: убираешь всё больше и больше кода из ошибочной программы, пока не остаётся сравнительно небольшой фрагмент, при работе которого до сих пор возникает проблема. То есть отрезаешь от программы по куску, пока не остаётся та часть, что содержит баг.

Но дело в том, что очень трудно вырезать куски из видеоигры. Как её запускать, если ты убрал код, эмулирующий гравитацию? Или отрисовывающий персонажей?

Поэтому приходится заменять целые модули заглушками, которые притворяются, что делают нечто полезное, а на самом деле выполняют что-то очень простое, что не может содержать ошибок. Приходится писать такие костыли, чтобы игра хотя бы работала. Это медленный и болезненный процесс.

Короче, я это сделал. Удалял всё новые и новые куски кода, пока не остался начальный код, который настраивает систему для запуска игры, инициализирует оборудование для отрисовки и т.д. Конечно, на этой стадии я не мог сделать меню сохранения и загрузки, потому что пришлось бы делать заглушку для всего кода, отвечающего за графику. Но я мог притвориться пользователем, который использует (невидимый) экран сохранения и загрузки и просит сохранить, а потом записать на карту памяти.

В результате у меня остался небольшой фрагмент кода, с которым всё ещё возникала вышеупомянутая проблема но до сих пор это происходило случайным образом! Чаще всего всё работало нормально, но изредка возникали сбои. Я убрал почти весь код игры, но баг всё ещё жил. Это озадачивало: оставшийся код на самом деле ничего не делал.

В какой-то момент, вероятно, в три утра, мне в голову пришла мысль. Операции чтения и записи (ввода-вывода) подразумевают точное время выполнения. Когда работаешь с жёстким диском, картой памяти или Bluetooth-модулем, низкоуровневый код, отвечающий за чтение и запись, делает это в соответствии с часами.

С помощью часов устройство, которое не связано напрямую с процессором, синхронизируется с исполняемым в процессоре кодом. Часы определяют частоту бодов скорость передачи данных. Если с таймингами возникает путаница, то также путается либо оборудование, либо ПО, либо они оба. И это очень плохо, потому что данные могут повредиться.

А вдруг что-то в нашем коде путает тайминги? Я проверил всё, что с этим связано, в коде тестовой программы, и заметил, что мы задали программируемому таймеру в PS1 частоту 1 кГц (1000 тактов в секунду). Это довольно много, по умолчанию при запуске приставки он работает с частотой 100 Гц. И большинство игр использует именно эту частоту.

Энди, разработчик игры, задал таймеру частоту 1 кГц чтобы движения вычислялись точнее. Энди склонен к чрезмерности, и если мы эмулируем гравитацию, то делаем это настолько точно, насколько возможно!

Но что если ускорение таймера как-то повлияло на общий тайминг программы, а значит и на часы, которые регулируют частоту бодов для карты памяти?

Я закомментировал код с таймером. Ошибка больше не повторялась. Но это не означает, что мы её исправили, ведь сбой возникал случайным образом. А вдруг мне просто повезло?

Через несколько дней я снова экспериментировал с тестовой программой. Баг не повторялся. Я вернулся к полной кодовой базе игры и изменил код сохранения и загрузки так, чтобы программируемый таймер сбрасывался в исходное значение (100 Гц) перед обращением к карте памяти, а затем снова возвращался к 1 кГц. Сбоев больше не возникало.

Но почему так произошло?

Я снова вернулся к тестовой программе. Попробовал найти какую-то закономерность в возникновении ошибки при таймере в 1 кГц. В конце концов я заметил, что ошибка возникает, когда кто-то играет с контроллером PS1. Поскольку сам я редко это делал бы зачем мне контроллер при тестировании кода сохранения и загрузки? то я и не замечал этой зависимости. Но однажды один из наших художников ждал, когда я закончу тестирование, наверняка в тот момент я ругался, и нервно крутил контроллер в руках. Возникла ошибка. Погоди, что?! Ну-ка сделай так снова!.

Когда я понял, что эти два события взаимосвязаны, то смог легко воспроизвести ошибку: начал записывать на карту памяти, пошевелил контроллер, испортил карту памяти. Для меня это выглядело как аппаратный баг.

Я пришёл к Конни и рассказал о своём открытии. Она передала информацию одному из инженеров, проектировавшему PS1. Невозможно, ответил он, это не может быть аппаратной проблемой. Я попросил Конни устроить нам беседу.

Инженер позвонил мне, и мы поспорили с ним на его ломаном английском и моём (крайне) ломаном японском. Наконец я сказал: Давайте я просто пришлю свою тестовую программу в 30 строк, при которой движение контроллера приводит к багу. Он согласился. Заявил, что это потеря времени, и что он ужасно занят работой над новым проектом, но уступит, потому что мы очень важный разработчик для Sony. Я подчистил свою тестовую программу и отправил ему.

На следующий вечер (мы были в Лос-Анджелесе, а он в Токио) он позвонил мне и смущённо извинился. Это была аппаратная проблема.

Я не знаю, в чём именно заключался баг, но, насколько я слышал в штаб-квартире Sony, если задать таймеру достаточно высокое значение, то это мешало компонентам на материнской плате поблизости от кристалла таймера. Одним из них был контроллер частоты бодов для карты памяти, который также задавал частоту бодов для контроллеров. Я не инженер, так что мог что-то напутать.

Но суть в том, что между компонентами на материнской плате возникали помехи. И при одновременной передаче данных через порт контроллера и порт карты памяти при таймере, работающем с частотой 1 кГц, биты пропадали, данные терялись, а карта повреждалась.

Сбойные коровы


В 1980-х мой ментор Сергей писал ПО для СМ-1800, советского клона PDP-11. Этот микрокомпьютер только что установили на ЖД-станции под Свердловском, важным транспортным узлом СССР. Новая система была спроектирована для маршрутизации вагонов и грузопотоков. Но в ней оказался досадный баг, который приводил к случайным сбоям и падениям. Падения возникали всегда, когда кто-то уходил вечером домой. Но несмотря на тщательное расследование на следующий день, при всех ручных и автоматических тестах компьютер работал корректно. Обычно это свидетельствует о состоянии гонки или каком-то ином баге конкурентности, который проявляется при определённых условиях. Устав от звонков поздней ночью, Сергей решил докопаться до сути, и первым делом понять, какие условия на сортировочной станции приводили к поломке компьютера.

Сначала он собрал статистику всех необъяснимых падений и построил график по датам и времени. Паттерн был очевиден. Понаблюдав ещё несколько дней, Сергей понял, что легко может спрогнозировать время будущих системных сбоев.

Вскоре он выяснил, что сбои возникали только тогда, когда на станции сортировали вагоны с крупным рогатым скотом из северной Украины и западной России, направлявшиеся на близлежащую скотобойню. Это само по себе было странно, ведь скотобойню снабжали хозяйства, находившиеся гораздо ближе, в Казахстане.

Чернобыльская АЭС взорвалась в 1986-м, и радиоактивные осадки сделали непригодными к обитанию прилегающие территории. Загрязнению подверглись обширные территории в северной Украине, Белоруссии и западной России. Заподозрив высокий уровень радиации в прибывающих вагонах, Сергей разработал метод проверки этой теории. Населению иметь дозиметры запрещалось, поэтому Сергей проставился нескольким военным на ЖД-станции. После нескольких порций водки ему удалось убедить солдата измерить уровень радиации в одном из подозрительных вагонов. Оказалось, что уровень в разы превышает обычные значения.

Мало того, что скот сильно фонил радиацией, её уровень был настолько велик, что это приводило к случайному выпадению битов в памяти СМ-1800, которая стояла в здании рядом со станцией.

В СССР возникала нехватка продуктов питания, и власти решили смешивать мясо из Чернобыльской области с мясом из других областей страны. Это позволяло снизить общий уровень радиоактивности без потери ценных ресурсов. Узнав об этом, Сергей сразу же заполнил документы на эмиграцию. А падения компьютера прекратились сами собой, когда уровень радиации снизился со временем.

По трубам


Когда-то компания Movietech Solutions создала ПО для кинотеатров, предназначенное для учёта и продажи билетов и общего управления. DOS-версия флагманского приложения была довольно популярна среди небольших и средних сетей кинотеатров в Северной Америке. Поэтому не удивительно, что когда анонсировали версию под Windows 95, интегрированную с новейшими сенсорными экранами и киосками самообслуживания, а также оснащённую всевозможными средствами отчётности, она тоже быстро стала популярной. Чаще всего обновление проходило без проблем. ИТ-специалисты на местах устанавливали новое оборудование, мигрировали данные, и бизнес продолжался. За исключением случаев, когда не продолжался. Когда такое происходило, компания отправляла Джеймса по прозвищу Чистильщик.

Хотя это прозвище намекает на гнусного типа, однако чистильщик это лишь сочетание инструктора, установщика и мастера на все руки. Джеймс мог провести несколько дней у клиента, собирая все компоненты воедино, а затем ещё пару дней учил персонал пользоваться новой системой, решая любые возникающие проблемы с оборудованием и фактически помогая программному обеспечению пройти период становления.

Поэтому не удивительно, что в это суматошное время Джеймс пришёл утром в офис, и не успел дойти до своего стола, как его встретил руководитель, наполненный кофеином сверх обычного.

Боюсь, тебе нужно как можно скорее отправиться в Аннаполис в Новой Шотландии. У них легла вся система, и после ночи совместной работы с их инженерами мы не можем понять, что произошло. Похоже, на сервере отказала сеть. Но только после того, как система проработала несколько минут.

Они не вернулись к старой системе? совершенно серьёзно ответил Джеймс, хотя мысленно он вытаращил глаза от удивления.

Именно: у их айтишника изменились приоритеты и он решил уйти с их старым сервером. Джеймс, они установили систему на шести площадках и только что заплатили за премиальную поддержку, а их бизнес сейчас ведётся как в 1950-х.

Джеймс слегка выпрямился.

Это другое дело. Ладно, приступаю.

Когда он прибыл в Аннаполис, то первым делом нашёл первый кинотеатр клиента, в котором возникла проблема. На взятой в аэропорте карте всё выглядело прилично, но окрестности нужного адреса выглядели подозрительно. Не гетто, но напоминали фильмы в жанре нуар. Когда Джеймс припарковался у обочины в центре, к нему приблизилась проститутка. Учитывая размер Аннаполиса, она, скорее всего, была единственная на весь город. Её появление сразу же напомнило о знаменитом персонаже, который на большом экране предлагал секс за деньги. Нет, не о Джулии Робертс, а о Джоне Войте [намёк на фильм Полуночный ковбой прим. пер.].

Отправив проститутку восвояси, Джеймс отправился к кинотеатру. Окрестности стали получше, но всё равно создавалось впечатление захудалости. Не то чтобы Джеймс слишком беспокоился. Он уже бывал в убогих местах. А это была Канада, в которой даже грабители достаточно вежливы, чтобы сказать спасибо после того, как отобрали ваш бумажник.

Боковой вход в кинотеатр находился в промозглой аллее. Джеймс подошёл к двери и постучал. Вскоре она заскрипела и приоткрылась.

Вы чистильщик? раздался изнутри хриплый голос.

Да, это я я приехал, чтобы всё исправить.

Джеймс прошёл в фойе кинотеатра. Вероятно, не имея другого выхода, персонал начал выдавать посетителям бумажные лотерейные билеты. Это затрудняло финансовую отчётность, не говоря уже о более интересных подробностях. Но сотрудники встретили Джеймса с облегчением и немедленно отвели в серверную.

На первый взгляд всё было в порядке. Джеймс залогинился на сервер и проверил обычные подозрительные места. Никаких проблем. Однако из предосторожности Джеймс выключил сервер, заменил сетевую карту и откатил систему. Она моментально заработала в полном объёме. Персонал снова начал продавать билеты.

Джеймс позвонил Марку и сообщил о ситуации. Не трудно предположить, что Джеймс может захотеть задержаться здесь и посмотреть, не произойдёт ли что-нибудь неожиданное. Он спустился по лестнице и начал расспрашивать сотрудников и произошедшем. Очевидно, что система перестала работать. Они её выключили и включили, всё заработало. Но спустя 10 минут система отвалилась.

Как раз в этот момент произошло нечто подобное. Внезапно система для продажи билетов начала выдавать ошибки. Сотрудники вздохнули и сгребли лотерейные билеты, а Джеймс поспешил в серверную. С сервером всё выглядело хорошо.

Затем вошёл один из сотрудников.

Система опять работает.

Джеймс был озадачен, ведь он ничего не сделал. Точнее, ничего такого, что заставило бы систему работать. Он разлогинился, взял телефон и позвонил в службу поддержки своей компании. Вскоре в серверную вошёл тот же сотрудник.

Система лежит.

Джеймс взглянул на сервер. На экране танцевал интересный и знакомый узор из разноцветных форм хаотично извивающиеся и переплетающиеся трубы. Все мы когда-то видели этот скринсейвер. Он был прекрасно отрисован и буквально гипнотизировал.


Джеймс нажал кнопку и узор исчез. Он поторопился к билетной кассе и по пути встретил возвращавшегося к нему сотрудника.

Система опять работает.

Если можно мысленно сделать фейспалм, то именно это Джеймс и сделал. Скринсейвер. Он использует OpenGL. И поэтому во время работы потребляет все ресурсы серверного процессора. В результате каждое обращение к серверу завершается по таймауту.

Джеймс вернулся в серверную, залогинился и заменил скринсейвер с прекрасными трубами на пустой экран. То есть вместо скринсейвера, поглощающего 100 % ресурсов процессора, поставил другой, не потребляющий ресурсы. Затем подождал 10 минут, чтобы проверить свою догадку.

Когда Джеймс приехал в следующий кинотеатр, он задумался о том, как объяснить своему руководителю, что он только что пролетел 800 км, чтобы отключить скринсейвер.

Сбой в определённую фазу Луны


Правдивая история. Однажды возник программный баг, который зависел от фазы Луны. Там была маленькая подпрограмма, которая обычно использовалась в разных программах MIT для вычисления приближения к истинной фазе Луны. GLS встроила эту подпрограмму в программу на LISP, которая при записи файла выводила строку с временной меткой длиной почти 80 символов. Очень редко первая строка сообщения получалась слишком длинной и переходила на следующую строку. И когда программа потом читала этот файл, она ругалась. Длина первой строки зависела от точной даты и времени, а также от длины спецификации фазы в момент печати временной метки. То есть баг в буквальном смысле зависел от фазы Луны!

Первое бумажное издание Jargon File (Steele-1983) содержало образец такой строки, приводившей к описанному багу, однако наборщик исправил её. С тех пор это описывают как баг фазы Луны.

Однако будьте осторожны с предположениями. Несколько лет назад инженеры из CERN (European Center for Nuclear Research) столкнулись с ошибками в экспериментах, проводившихся на Большом электрон-позитронном коллайдере. Поскольку компьютеры активно обрабатывают гигантское количество данных, генерируемых этим устройством, прежде чем показать результат учёным, многие предполагали, что ПО каким-то образом чувствительно к фазе Луны. Несколько отчаянных инженеров докопались до истины. Ошибка возникала из-за небольшого изменения геометрии кольца длиной 27 км в связи с деформацией Земли при проходе Луны! Эта история вошла в фольклор физиков как Ньютоновская месть физике частиц и пример связи простейших и старейших физических законов с наиболее передовыми научными концепциями.

Смывание в туалете останавливает поезд


Лучший аппаратный баг, о котором я слышал, был в скоростном поезде во Франции. Баг приводил к аварийному торможению состава, но только если на борту были пассажиры. При каждом таком случае поезд выводили из эксплуатации, проверяли, но ничего не находили. Затем его снова отправляли на линию, и он моментально аварийно останавливался.

Во время одной из проверок инженер, ехавший в поезде, пошёл в туалет. Вскоре он смыл за собой, БУМ! Аварийная остановка.

Инженер связался с машинистом и спросил:

Что ты делал перед самым торможением?

Ну, я притормаживал на спуске

Это было странно, потому что при обычном курсировании поезд притормаживает на спусках десятки раз. Состав отправился дальше, и на следующем спуске машинист предупредил:

Я собираюсь притормаживать.

Ничего не произошло.

Что ты делал при последнем торможении? спросил машинист.

Ну я был в туалете

Ну, тогда иди в туалет и сделай то, что делал, когда будем спускаться опять!

Инженер отправился в туалет, и когда машинист предупредил: Я торможу, он спустил воду. Конечно же, поезд тут же остановился.

Теперь они могли воспроизвести проблему и нужно было найти причину.

Через две минуты они заметили, что кабель дистанционного управления торможением двигателя (у поезда было по одному двигателю в обоих концах) отсоединён от стенки электрошкафа и лежит на реле, управляющем соленоидом туалетной заглушки Когда реле включалось, оно создавало помехи в тормозном кабеле, и система защиты от сбоев просто включала аварийное торможение.

Шлюз, ненавидевший FORTRAN


Несколько месяцев назад мы заметили, что сетевые подключения к сети на материке [дело было на Гавайях] становились очень-очень медленными. Это могло длиться 10-15 минут, а затем неожиданно возникало снова. Спустя некоторое время мой коллега пожаловался мне, что подключения к сети на материке вообще не работают. У него был какой-то код на FORTRAN, который нужно было скопировать на машину на материке, но это не получалось, потому что сеть не держалась достаточно долго, чтобы завершилась загрузка по FTP.

Да, получалось так, что отказы сети возникали тогда, когда коллега пытался передать по FTP файл с исходным кодом на FORTRAN на машину на материке. Мы попробовали архивировать файл: тогда он спокойно копировался (но на целевой машине не было распаковщика, так что проблема не была решена). Наконец мы разделили код на FORTRAN на очень маленькие фрагменты и отправили их по очереди. Большинство фрагментов скопировалось без проблем, но несколько штук не прошли, либо прошли после многочисленных попыток.

Изучив проблемные фрагменты, мы обнаружили, что у них есть кое-что общее: все они содержат блоки комментариев, которые начинаются и заканчиваются строками, состоящими из прописных букв С (так коллега предпочитал комментировать на FORTRAN). Мы отправили на материк электронные письма специалистам по сетям и попросили о помощи. Конечно, им захотелось увидеть образцы наших файлов, не поддающихся пересылке по FTP но наши письма до них не дошли. Наконец мы придумали просто описать, как выглядят непересылаемые файлы. Это сработало :) [Осмелюсь ли я добавить сюда пример одного из проблемных комментариев на FORTRAN? Наверное, не стоит!]

В конце концов нам удалось разобраться. Между нашей частью кампуса и выходом в сеть на материке недавно установили новый шлюз. У него были ОГРОМНЕ трудности с передачей пакетов, которые содержали повторяющиеся фрагменты из прописных С! Всего несколько таких пакетов могли занять все ресурсы шлюза и не позволяли пробиться большинству других пакетов. Мы пожаловались производителю шлюза и нам ответили: А, да, вы столкнулись с багом повторяющихся С! Мы о нём уже знаем. В конце концов мы решили проблему, купив новый шлюз другого производителя (в защиту первого скажу, что неспособность передавать программы на FORTRAN для кого-то может оказаться преимуществом!).

Трудные времена


Несколько лет назад, работая над созданием ETL-системы на Perl, предназначенной для снижения расходов на третий этап клинических испытаний, мне потребовалось обработать около 40 000 дат. Две из них не прошли проверку. Меня это не слишком обеспокоило, потому что эти даты были взяты из предоставленных клиентом данных, которые часто, скажем так, удивляли. Но когда я проверил исходные данные, оказалось, что этим датами были 1 января 2011 и 1 января 2007. Я подумал, что баг содержится в только что написанной мной программе, но оказалось, ему уже 30 лет. Это может звучать таинственно для тех, кто не знаком с экосистемой программного обеспечения. Из-за давнего решения другой компании, принятого ради заработка денег, мой клиент заплатил мне за исправление бага, который одна компания внесла случайно, а другая намеренно. Чтобы вы поняли, о чём речь, мне нужно рассказать о компании, которая добавила фичу, в результате ставшую багом, а также ещё о нескольких любопытных событиях, внёсших вклад в исправленный мной таинственный баг.

В старые добрые времена компьютеры Apple иногда спонтанно сбрасывали свою дату на 1 января 1904 года. Причина была простой: для отслеживания даты и времени использовались работающие от батарейки системные часы. Что происходило, когда батарейка садилась? Компьютеры начинали отслеживать дату по количеству секунд с начала эпохи. Под эпохой подразумевалась референсная исходная дата, и для Macintoshей это было 1 января 1904. И после умирания батарейки текущая дата сбрасывалась на указанную. Но почему так происходило?

Раньше для хранения количества секунд с исходной даты Apple использовала 32 бита. Один бит может хранить одно из двух значений 1 или 0. Два бита могут хранить одно из четырёх значений: 00, 01, 10, 11. Три бита одно значение из восьми: 000, 001, 010, 011, 100, 101, 110, 111, и т.д. А 32 могли хранить одно из 232 значений, то есть 4 294 967 296 секунд. Для дат по версии Apple это равнялось примерно 136 годам, поэтому старые Маки не могут обрабатывать даты после 2040 года. И если системная батарейка садится, дата сбрасывается на 0 секунд с начала эпохи, и приходится вручную выставлять дату при каждом включении компьютера (или пока вы не купите новую батарейку).

Однако решение Apple хранить даты в виде секунд с начала эпохи означало, что мы не можем обрабатывать даты до начала эпохи, что имело далеко идущие последствия, как мы увидим. Apple ввела фичу, а не баг. Помимо прочего это означало, что операционная система Macintosh была неуязвима для бага миллениума (чего не скажешь про многие приложения для Мака, имевших собственные системы исчисления дат для обхода ограничений).

Идём дальше. Мы использовали Lotus 1-2-3, разработанное IBM киллер-приложение, которое помогло запустить PC-революцию, хотя на Apple-компьютерах была VisiCalc, обеспечившая успех персональным компьютерам. Справедливости ради, если бы 1-2-3 не появилась, PC вряд ли взлетели бы, а история персональных компьютеров могла развиваться бы совсем иначе. Lotus 1-2-3 некорректно обрабатывала 1900-й как високосный год. Когда Microsoft выпустила свою первую электронную таблицу Multiplan, та заняла маленькую долю рынка. И когда запустили проект Excel, решили не только скопировать у Lotus 1-2-3 схему именования строк и колонок, но и обеспечить совместимость по багам, сознательно обрабатывая 1900-й как високосный год. Эта проблема существует по сей день. То есть в 1-2-3 это было багом, а в Excel сознательным решением, которое гарантировало, что все пользователи 1-2-3 могут импортировать свои таблицы в Excel без изменения данных, даже если они ошибочные.

Но тут была ещё одна проблема. Сначала Microsoft выпустила Excel для Macintosh, который не признавал даты до 1 января 1904. А в Excel началом эпохи считалось 1 января 1900 года. Поэтому разработчики внесли изменение, чтобы их программа распознавала вид эпохи и хранила внутри себя данные в соответствии с нужной эпохой. Microsoft даже написала об этом поясняющую статью. И это решение привело к моему багу.

Моя ETL-система получала от покупателей Excel-таблицы, которые создавались под Windows, но могли быть созданы и на Маке. Поэтому началом эпохи в таблице могло быть как 1 января 1900 года, так и 1 января 1904 года. Как это узнать? Формат файла Excel показывает нужную информацию, а парсер который я применял, не показывал (теперь показывает), и предполагал, что вы знаете эпоху для конкретной таблицы. Наверное, можно было потратить больше времени на то, чтобы разобраться в двоичном формате Excel и прислать патч автору парсера, но мне нужно было сделать для клиента много другого, поэтому я быстро написал эвристику для определения эпохи. Она была простой.

В Excel дата 5 июля 1998 может быть представлена в формате 07-05-98 (бесполезная американская система), Jul 5, 98, July 5, 1998, 5-Jul-98 или в каком-нибудь другом бесполезном формате (по иронии судьбы, одним из форматов, который не предлагала моя версия Excel, был стандарт ISO 8601). Однако внутри таблицы неформатированная дата хранилась либо как 35981 для эпохи-1900, либо как 34519 для эпохи-1904 (числа представляют количество дней с начала эпохи). Я просто с помощью простого парсера извлекал год из отформатированной даты, а затем с помощью парсера Excel извлекал год из неотформатированной даты. Если оба значения отличались на 4 года, от я понимал, что использую систему с эпохой-1904.

Почему я не использовал просто отформатированные даты? Потому что 5 июля 1998 может быть отформатировано как July, 98 с потерей дня месяца. Мы получали таблицы от такого количества компаний, которые создавали их такими разными способами, что разбираться с датами должны были мы (в данном случае я). Кроме того, если Excel понимает правильно, то и мы должны!

Тогда же я столкнулся с 39082. Напомню, что Lotus 1-2-3 считал 1900-й високосным, и это добросовестно повторили в Excel. А поскольку это добавляло к 1900-му один день, многие функции вычисления дат могли ошибаться на этот самый день. То есть 39082 могло быть 1 января 2011 (на Маках) или 31 декабря 2006 (в Windows). Если мой парсер лет извлекал из отформатированного значения 2011-й год, то всё хорошо. Но поскольку парсер Excel не знает, какая используется эпоха, он по умолчанию применяет эпоху-1900, возвращая 2006-й год. Моё приложение видело, что разница составляет 5 лет, считало это ошибкой, журналировало и возвращало неотформатированное значение.

Чтобы это обойти, я написал вот это (псевдокод):

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

И тогда все 40 000 дат отпарсились корректно.

Посреди больших заданий на печать


В начале 1980-х мой отец работал в Storage Technology, в не существующем ныне подразделении, которое создавало ленточные накопители и пневматические системы для высокоскоростной подачи лент.

Они так переделывали накопители, чтобы те могли иметь один центральный привод А, соединённый с семью приводами Б, а маленькая ОС в оперативной памяти, управлявшая приводом А, могла делегировать операции чтения и записи по всем приводам Б.

При каждом запуске привода А нужно было вставлять дискету в периферийный дисковод, подключённый к А, чтобы загрузить в его память операционную систему. Она была крайне примитивной: вычислительная мощность обеспечивалась 8-битным микроконтроллером.

Целевой аудиторией такого оборудования были компании с очень большими хранилищами данных банки, розничные сети и т.д., которым нужно было печатать много ярлыков с адресами или банковских выписок.

У одного клиента была проблема. Посреди задания на печать один конкретный привод А мог перестать работать, из-за чего вставало всё задание. Чтобы восстановить работу привода, персоналу приходилось всё перезагружать. И если это происходило посреди шестичасового задания, то терялось огромное количество дорогостоящего компьютерного времени и срывалось расписание всей операции.

Из Storage Technologies отправили техников. Но несмотря на все попытки, они не смогли воспроизвести баг в тестовых условиях: похоже, сбой возникал посреди больших заданий на печать. Проблема была не в оборудовании, они заменили всё, что могли: оперативную память, микроконтроллер, дисковод, все мыслимые части ленточного привода проблема сохранялась.

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

Эксперт взял кресло и чашку кофе, сел в компьютерном зале в те времена были комнаты, специально выделенные под компьютеры и смотрел, как персонал ставит в очередь большое задание на печать. Эксперт ждал, чтобы произошёл сбой и тот произошёл. Все посмотрели на Эксперта а у того не было никаких идей, почему так произошло. Поэтому он приказал снова поставить задание в очередь, и все сотрудники с техниками вернулись к работе.

Эксперт опять сел в кресло и стал ждать сбоя. Прошло около шести часов, и сбой произошёл. У Эксперта опять не было идей, не считая того, что всё случилось в заполненном людьми помещении. Он приказал перезапустить задание, снова сел и стал ждать.

К третьему сбою Эксперт кое-что заметил. Сбой происходил тогда, когда персонал менял ленты в постороннем приводе. Более того, сбой возникал, как только один из сотрудников проходил через определённую плитку на полу.

Фальшпол был сделан из алюминиевых плиток, уложенных на высоте 68 дюймов. Под фальшполом проходили многочисленные провода от компьютеров, чтобы кто-нибудь случайно не наступил на важный кабель. Плитки были уложены очень плотно, чтобы под фальшпол не попадал мусор.

Эксперт понял, что одна из плиток была деформирована. Когда сотрудник наступал на её угол, плитка тёрлась краями о соседние плитки. С ними тёрлись и пластмассовые детали, соединявшие плитки, из-за чего возникали статические микроразряды, создававшие радиочастотные помехи.

Сегодня оперативная память гораздо лучше защищена от радиочастотных помех. Но в те годы это было не так. Эксперт понял, что эти помехи нарушали работу памяти, а с ней и работу операционной системы. Он позвонил в службу сопровождения, заказал новую плитку, сам её установил, и проблема исчезла.

Это прилив!


История произошла в серверной комнате, на четвёртом или пятом этаже офиса в Портсмуте (кажется), в районе доков.

Однажды упал Unix-сервер с основной базой данных. Его перезагружали, но он радостно продолжал раз за разом падать. Решили позвать кого-нибудь из службы поддержки.

Чувак из поддержки кажется, его звали Марк, но это не важно вряд ли я с ним знаком. Это не важно, правда. Остановимся на Марке, хорошо? Отлично.

Итак, через несколько часов прибыл Марк (от Лидса до Портсмута путь не близкий, знаете ли), включил сервер и всё заработало без проблем. Типичная чёртова поддержка, клиент из-за этого очень расстраивается. Марк просматривает файлы журнала и не находит ничего предосудительного. Тогда Марк возвращается на поезд (или на каком там виде транспорта он приехал, это могла быть и хромая корова, насколько я знаю короче, это не важно, ладно?) и отправляется обратно в Лидс, впустую потратив день.

Тем же вечером сервер падает снова. История та же сервер не поднимается. Марк удалённо пытается помочь, но клиент не может запустить сервер.

Опять поезд, автобус, лимонное безе или ещё какая-то херня, и Марк опять в Портсмуте. Глянь-ка, сервер загружается без проблем! Чудо. Марк несколько часов проверяет, что с операционкой или ПО всё в порядке, и отправляется в Лидс.

Примерно в середине дня сервер падает (полегче!). На этот раз кажется разумным привлечь людей из аппаратной поддержки, чтобы они заменили сервер. Но нет, примерно через 10 часов он тоже падает.

Ситуация повторялась несколько дней. Сервер работает, примерно через 10 часов падает и не запускается в течение следующих 2 часов. Они проверили охлаждение, утечки памяти, они проверили всё, но ничего не нашли. Затем сбои прекратились.

Неделя прошла беззаботно все были счастливы. Счастливы, пока всё не началось опять. Картина та же. 10 часов работы, 23 часа простоя

А потом кто-то (кажется, мне говорили, что этот человек не имел отношения к ИТ) сказал:

Это прилив!

Возглас встретили пустыми взглядами, и, вероятно, чья-то рука поколебалась у кнопки вызова охраны.

Он перестаёт работать с приливом.

Казалось бы, это совершенно чуждая концепция для сотрудников ИТ-поддержки, которые вряд ли читают ежегодник приливов, сидя за кофе. Они объяснили, что это никак не может быть связано с приливом, потому что сервер работал неделю без сбоев.

На прошлой неделе прилив был низким, а на этой высоким.

Немного терминологии для тех, у кого нет лицензии на управление яхтой. Приливы зависят от лунного цикла. И по мере вращения Земли, каждые 12,5 часа гравитационное притяжение Солнца и Луны создаёт приливную волну. В начале 12,5-часового цикла возникает прилив, в середине цикла отлив, а в конце снова прилив. Но поскольку орбита Луны меняется, меняется и разница между отливом и приливом. Когда Луна находится между Солнцем и Землёй или с противоположной стороны от Земли (полнолуние или отсутствие Луны), мы получаем сизигийские приливы самые высокие приливы и самые низкие отливы. В полулуние мы получаем квадратурные приливы самые низкие приливы. Разница между двумя экстремумами сильно уменьшается. Лунный цикл длится 28 дней: сизигийские квадратурные сизигийские квадратурные.

Когда технарям объяснили суть приливных сил, те сразу же подумали о том, что нужно позвонить в полицию. И вполне логично. Но оказалось, что чувак был прав. За две недели до этого неподалёку от офиса пришвартовался эсминец. Каждый раз, когда прилив поднимал его на определённую высоту, радарный пост корабля оказывался на уровне пола серверной. И радар (или средство РЭБ, или какая-то другая игрушка военных) устраивал в компьютерах хаос.

Полётное задание для ракеты


Мне поручили портировать большую (около 400 тыс. строк) систему управления и контроля запуска ракет под новые версии операционной системы, компилятора и языка. Точнее, с Solaris 2.5.1 на Solaris 7, и с Verdix Ada Development System (VADS), написанной на Ada 83, на систему Rational Apex Ada, написанную на Ada 95. VADS была куплена компанией Rational, и её продукт устарел, хотя Rational постаралась реализовать совместимые версии специфических для VADS пакетов, чтобы облегчить переход на компилятор Apex.

Три человека помогали мне просто получить чисто скомпилированный код. На это ушло две недели. А затем я самостоятельно работал над тем, чтобы заставить систему работать. Короче, это были худшие архитектура и реализация программной системы, что мне встречались, поэтому на завершение портирования ушло ещё два месяца. Затем систему передали на тестирование, что заняло ещё несколько месяцев. Я сразу исправлял баги, которые находили при тестировании, но их количество быстро снизилось (исходный код был production-системой, поэтому его функциональность работала достаточно надёжно, мне лишь пришлось убрать баги, возникшие при адаптации под новый компилятор). В конце концов, когда всё работало так, как и должно было, меня перевели на другой проект.

А в пятницу перед Днём благодарения раздался телефонный звонок.

Примерно через три недели должны были протестировать запуск ракеты, и в ходе лабораторных испытаний обратного отсчёта последовательность команд оказалась заблокированной. В реальной жизни это привело бы к прерыванию испытаний, а если блокировка возникла бы в течение нескольких секунд после запуска двигателя, то во вспомогательных системах произошло бы несколько необратимых действий, из-за которых пришлось бы долго и дорого заново готовить ракету. Она не стартовала бы, но очень много людей сильно расстроилось бы из-за потери времени и очень, очень больших денег. Не позволяйте никому говорить вам, что министерство обороны бесцеремонно расходует деньги я еще не встречал ни одного менеджера по контрактной деятельности, для которого бюджет не был бы на первом или втором месте, а следом за ним график.

В предыдущие месяцы это испытание обратного отсчёта прогонялось сотни раз во многих вариантах, и было лишь несколько мелких заминок. Так что вероятность возникновения этой была очень низкой, однако её последствия были очень значительны. Перемножьте оба этих фактора, и поймёте, что новость предрекала мне и десяткам инженеров и менеджеров испорченную праздничную неделю.

И внимание было обращено на меня, как на человека, портировавшего систему.

Как и в большинстве систем, для которых критически важна безопасность, здесь журналировалось множество параметров, так что удалось довольно легко определить несколько строк кода, исполненных перед зависанием системы. И конечно же, в них не было абсолютно ничего необычного, те же самые выражения успешно исполнялись буквально тысячи раз в ходе того же прогона.

Мы позвали в Rational людей из Apex, поскольку это они разработали компилятор и в подозрительном коде вызывались некоторые разработанные ими подпрограммы. На них (и всех других) произвело впечатление, что нужно выяснить причину проблемы буквально национального значения.

Поскольку в журналах не было ничего интересного, решили попытаться воспроизвести проблему в местной лаборатории. Это была непростая задача, поскольку событие возникало примерно один раз на 1000 прогонов. Одной из предполагаемых причин было то, что вызов разработанной поставщиком мьютекс-функции (часть пакета миграции VADS) Unlock не приводил к разблокированию. Поток обработки, вызывавший функцию, обрабатывал heartbeat-сообщения, которые номинально приходили каждую секунду. Мы подняли частоту до 10 Гц, то есть 10 раз в секунду, и начали прогон. Примерно через час система заблокировалась. В журнале мы увидели, что последовательность записанных сообщений была такой же, как во время сбойного испытания. Сделали ещё несколько прогонов, система стабильно блокировалась через 4590 минут после начала, и каждый раз в журнале была одна и та же трасса. Несмотря на то, что технически мы сейчас исполняли другой код частота сообщений была другой поведение системы повторялось, поэтому мы уверились, что этот нагрузочный сценарий приводил к той же проблеме.

Теперь нужно было выяснить, где именно в последовательности выражений возникала блокировка.

В этой реализации системы использовалась система задач Ada, и использовалась невероятно плохо. Задачи это высокоуровневая параллельно исполняемая конструкция в Ada, что-то вроде потоков исполнения, только встроенная в сам язык. Когда двум задачам нужно взаимодействовать, они назначают рандеву (rendezvous), обмениваются нужными данными, а затем прекращают рандеву и возвращаются к своим независимым исполнениям. Однако система была реализована иначе. После того, как с целевой задачей проводилось рандеву, эта целевая задача проводила рандеву с другой задачей, которая потом проводила рандеву с третьей, и так далее, пока не завершалась какая-то обработка. После этого все эти рандеву завершались и каждая задача должна была вернуться к своему исполнению. То есть мы имели дело с самой дорогой в мире системой вызова функций, которая стопорила весь многозадачный процесс, пока обрабатывала часть входных данных. И раньше это не приводило к проблемам лишь потому, что пропускная способность была очень низкой.

Я описал этот механизм задач потому, что когда запрашивалось рандеву или ожидалось его завершение, могло происходить переключение задач. То есть процессор мог начать обработку другой задачи, готовой к выполнению. Получается, что когда одна задача готова к рандеву с другой задачей, может начаться выполнение совершенно другой задачи, и в конце концов управление возвращается первому рандеву. И могут возникать другие события, которые приводят к переключению задачи; одно из таких событий вызов системной функции, например, печать или выполнение мьютекса.

Чтобы понять, какая строка кода приводила к проблеме, мне нужно было найти способ записывать прогресс прохождения последовательности выражений, при этом не инициируя переключение задачи, что может помешать возникновению сбоя. Поэтому я не мог воспользоваться Put_Line(), чтобы не выполнять операций ввода-вывода. Можно было задать переменную-счётчик или что-то подобное, но как мне посмотреть её значение, если я не могу выводить её на экран?

Также при изучении журнала выяснилось, что, несмотря на зависание обработки heartbeat-сообщений, которое блокировало все операции ввода-вывода процесса и не давало выполнять другие обработки, прочие независимые задачи продолжали исполняться. То есть работа блокировалась не целиком, только (критическая) цепочка задач.

Это была зацепка, необходимая для вычисления блокирующего выражения.

Я сделал Ada-пакет, который содержал задачу, перечисляемый тип и глобальную переменную этого типа. Перечисляемые литералы были привязаны к конкретным выражениям проблемной последовательности (например, Incrementing_Buffer_Index, Locking_Mutex, Mutex_Unlocked), а затем вставил в неё выражения присваивания, которые присваивали соответствующее перечисление глобальной переменной. Поскольку объектный код всего этого просто хранил постоянную в памяти, переключение задачи в результате его исполнения было крайне маловероятно. В первую очередь мы подозревали выражения, которые могли переключить задачу, поскольку блокировка возникала при исполнении, а не возвращении при обратном переключении задачи (по нескольким причинам).

Отслеживающая задача просто выполнялась в цикле и периодически проверяла, изменилось ли значение глобальной переменной. При каждом изменении значение сохранялось в файл. Затем недолгое ожидание и новая проверка. Я записывал переменную в файл потому, что задача исполнялась только тогда, когда система выбирала её для исполнения при переключении задачи в проблемной области. Что бы ни происходило в этой задаче, это не влияло бы на другие, не связанные с ней заблокированные задачи.

Ожидалось, что когда система дойдёт до исполнения проблемного кода, глобальная переменная будет сбрасываться при переходе к каждому следующему выражению. Затем произойдёт что-то, приводящее к переключению задачи, и поскольку частота его исполнения (10 Гц) ниже, чем у мониторящей задачи, монитор мог зафиксировать значение глобальной переменной и записать его. В нормальной ситуации я мог бы получить повторяющуюся последовательность подмножества перечислений: последние значения переменной на момент переключения задачи. При зависании глобальная переменная не должна больше меняться, и последнее записанное значение покажет, исполнение какого выражения не завершилось.

Запустил код с отслеживанием. Он завис. А мониторинг сработал как по маслу.

В журнале оказалась ожидаемая последовательность, которая прерывалась значением, указывающим, что был вызван мьютекс Unlock, а задача не завершена как и в случае с тысячами предыдущих вызовов.

Инженеры из Apex в это время лихорадочно анализировали свой код и нашли в мьютексе место, где, теоретически, могла возникать блокировка. Но её вероятность была очень мала, поскольку к блокировке могла привести лишь определённая последовательность событий, происходящих в определённое время. Закон Мёрфи, парни, это закон Мёрфи.

Чтобы защитить нужный фрагмент кода, я заменил вызовы мьютекс-функций (построенных на основе мьютекс-функциональности ОС) маленьким нативным мьютекс-пакетом Ada, чтобы с его помощью управлять доступом мьютексов к этому фрагменту.

Вставил в код и запустил тест. Семь часов спустя код продолжал работать.

Мой код передали в Rational, там его скомпилировали, дизассемблировали и проверили, что в нём не используется тот же подход, который применялся в проблемных мьютекс-функциях.

Это была самая многолюдная проверка кода в моей карьере :) В комнате со мной было около десяти инженеров и менеджеров, ещё десяток людей подключились по конференц-звонку и все они исследовали около 20 строк кода.

Код прошёл проверку, собрали новые исполняемые файлы и передали на формальное регрессионное тестирование. Пару недель спустя испытания обратного отсчёта прошли успешно, и ракета взлетела.

Ладно, это всё хорошо и прекрасно, но в чём суть этой истории?

Это была совершенно отвратительная проблема. Сотни тысяч строк кода, параллельное исполнение, свыше десятка взаимодействующих процессов, плохая архитектура и плохая реализация, интерфейсы для встроенных системы и миллионы потраченных долларов. Никакого давления, верно.

Я был не единственным, кто работал над этой проблемой, хотя и находился в центре внимания, поскольку делал портирование. Но хотя я и делал его, это не означает, что я разбирался со всеми сотнями тысяч строк кода, или хотя бы бегло просмотрел их. Код и журналы анализировали инженеры по всей стране, но когда они говорили мне свои гипотезы о причинах сбоя, мне хватало полминуты, чтобы опровергнуть их. И когда меня просили проанализировать теории, я перекладывал это на кого-нибудь другого, потому что мне было очевидно, что эти инженеры идут не тем путём. Звучит самонадеянно? Да, это так, но я отклонил гипотезы и запросы по другой причине.

Я понимал природу проблемы. Я не знал точно, где она возникает и почему, но я знал, что именно происходит.

За годы работы я накопил много знаний и опыта. Я был одним из пионеров использования Ada, понимал её достоинства и недостатки. Я знаю, как runtime-библиотеки Ada обрабатывают задачи и работают с параллельным исполнением. И я разбираюсь в низкоуровневом программировании на уровне памяти, регистров и ассемблера. Иными словами, у меня глубокие познания в своей сфере. И я использовал их для поиска причины проблемы. Я не просто обошёл баг, а понимал, как найти его в условиях очень чувствительной среды исполнения.

Такие истории борьбы с кодом не слишком интересны для тех, кто не знаком с особенностями и условиями такой борьбы. Но эти истории помогают понять, что требуется для решения действительно трудных проблем.

Для решения действительно трудных проблем вам нужно быть не просто программистом. Вам нужно понимать судьбу кода, как он взаимодействует со своим окружением и как работает само окружение.

И тогда у вас будет своя испорченная праздничная неделя.



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

Перевод Фольклор программистов и инженеров (часть 2)

20.08.2020 10:19:07 | Автор: admin

Продолжение подборки историй из интернета о том, как у багов иногда бывают совершенно невероятные проявления. Первая часть тут.

Больше магии


Несколько лет назад я шарился по шкафам, в которых располагался компьютер PDP-10, принадлежавший лаборатории искусственного интеллекта в MIT. И заметил маленький переключатель, приклеенный к раме одного из шкафов. Было видно, что это самоделка, добавленная одним из лабораторных умельцев (никто не знал, кем именно).

Вы не будете трогать неизвестный переключатель на компьютере, не зная, что он делает, потому что вы можете сломать компьютер. Переключатель был подписан совершенно невразумительно. У него было два положения, и на металлическом корпусе карандашом были накарябаны слова магия и больше магии. Переключатель стоял в положении больше магии. Я позвал одного из техников, чтобы он взглянул. Он прежде не видел такого. При внимательном рассмотрении выяснилось, что к переключателю идёт всего лишь один провод! Другой конец провода исчезал в мешанине кабелей внутри компьютера, но природа электричества подсказывает, что переключатель не будет ничего делать, пока к нему не подключишь два провода.

Было очевидно, что это чья-то глупая шутка. Убедившись, что переключатель ничего не делает, мы переключили его. Компьютер немедленно отрубился.

Представьте себе наше изумление. Мы списали произошедшее на совпадение, но всё равно вернули кнопку в положение больше магии, прежде чем запустить компьютер.

Год спустя я рассказал эту историю другому технику, Дэвиду Муну, насколько я помню. Он усомнился в моей адекватности, или заподозрил в вере в сверхъестественную природу того переключателя, или решил, что я дурачу его липовой историей. Чтобы доказать свои слова, я показал ему этот переключатель, всё ещё приклеенный к раме и с единственным проводом, по-прежнему в положении больше магии. Мы внимательно изучили переключатель и провод и обнаружили, что тот был подключён к заземлению. Это выглядело вдвойне бессмысленным: переключатель был не только электрически неработоспособен, но ещё и подключён к месту, которое ни на что не влияет. Мы перевели его в другое положение.

Компьютер сразу вырубился.

Мы обратились к находившемуся поблизости Ричарду Гринблатту, который давно работал техником в MIT. Он тоже никогда не видел переключатель. Осмотрел его, пришёл к выводу, что переключатель бесполезен, достал кусачки и отрезал провод. Затем мы включили компьютер и тот спокойно начал работать.

Мы до сих пор не знаем, как этот выключатель вырубал компьютер. Есть гипотеза, что поблизости от контакта заземления возникало небольшое короткое замыкание, а перевод положений переключателя менял электрическую ёмкость настолько, чтобы цепь прерывалась, когда через неё проходили импульсы длительностью в миллионные доли секунды. Но точно мы уже не узнаем. Можно лишь сказать, что переключатель был волшебным.

Он всё ещё лежит у меня в подвале. Наверное, это глупо, но обычно я храню его в положении больше магии.

В 1994-м было предложено ещё одно объяснение этой истории. Обратите внимание, что корпус переключателя был металлическим. Предположим, что контакт без второго провода был подключён к корпусу (обычно корпус заземляют, но бывают исключения). Корпус переключателя был соединён с корпусом компьютера, который, вероятно, был заземлён. Тогда в цепи заземления внутри машины может быть другой потенциал, чем в цепи заземления корпуса, а смена положения переключателя приводила к падению или всплеску напряжения, и машина перезагружалась. Вероятно, этот эффект обнаружил кто-то, кто знал о разнице потенциалов, и решил сделать такой шуточный переключатель.

OpenOffice не печатает по вторникам


Сегодня в блоге я наткнулся на упоминание об одном интересном баге. У некоторых людей возникали сбои при печати документов. Позднее кто-то отметил, что его жена пожаловалась на невозможность печатать по вторникам!

В отчётах о баге некоторые изначально жаловались на то, что это должен быть баг OpenOffice, потому что из всех других приложений печаталось без проблем. Другие отмечали, что проблема возникает и пропадает. Один пользователь нашёл решение: удалить OpenOffice и очистить от него систему, затем установить заново (любая простая задача на Ubuntu). Пользователь сообщил во вторник, что его проблема с печатью решилась.

Через две недели он написал (во вторник), что его решение всё-таки не сработало. Примерно через четыре месяца жена Ubuntu-хакера пожаловалась, что OpenOffice не печатает по вторникам. Представляю себе эту ситуацию:

Жена: Стив, принтер не работает по вторникам.

Стив: Это выходной день у принтера, конечно он не печатает по вторникам.

Жена: Я серьёзно! Я не могу печатать из OpenOffice по вторникам.

Стив: (недоверчиво) Ладно, покажи.

Жена: Я не могу тебе показать.

Стив: (закатив глаза) Почему?

Жена: Сегодня среда!

Стив: (кивает, медленно произносит) Верно.

Проблему удалось отследить до программы под названием file. Эта *NIX-утилита с помощью шаблонов определяет типы файлов. Например, если файл начинается с %!, а потом идёт PS-Adobe-, тогда это PostScript. Похоже, OpenOffice пишет данные в такой файл. Во вторник он берёт форму %%CreationDate: (Tue MMM D hh:mm:...). Ошибка в шаблоне для файлов Erlang JAM означала, что Tue в PostScript-файле распознавалось как файл Erlang JAM, и поэтому, предположительно, он не отправлялся на печать.

Шаблон для файла Erlang JAM выглядит так:

4 string Tue Jan 22 14:32:44 MET 1991 Erlang JAM file - version 4.2

А должен выглядеть так:

4 string Tue\ Jan\ 22\ 14:32:44\ MET\ 1991 Erlang JAM file - version 4.2

Учитывая множество типов файлов, которые пытается распознать эта программа (больше 1600), ошибки в шаблонах не удивляют. Но к частым ложноположительным срабатываниям приводит ещё и порядок сопоставления. В данном случае тип Erlang JAM сопоставлялся до типа PostScript.

Пакеты смерти


Я начал называть их так потому, что они были именно пакетами смерти.

Компания Star2Star сотрудничала с производителем аппаратного обеспечения, который создал две последние версии нашей локальной клиентской системы.

Около года назад мы выпустили обновление для этого оборудования. Всё начиналось довольно просто, в соответствии с обычным законом Мура. Больше, лучше, быстрее, дешевле. Новое оборудование было 64-битным, имело в 8 раз больше памяти, вмещало больше дисков и имело четыре гигабитных Ethernet-порта Intel (мой любимый производитель Ethernet-контроллеров). У нас было (и есть) много идей, как использовать эти порты. В общем, железка была захватывающей.

Новинка пулей просвистела через тесты производительности и функциональности. И скорость высокая, и надёжность. Идеально. Затем мы не спеша развернули оборудование на нескольких тестовых площадках. Конечно же, начали возникать проблемы.

Быстрый поиск в Google подсказывает, что у Ethernet-контроллера Intel 82574L было как минимум несколько проблем. В частности, проблемы с EEPROM, баги в ASPM, выкрутасы с MSI-X и т.д. Мы несколько месяцев решали каждую из них. И думали, что закончили.

Но нет. Стало только хуже.

Я думал, что разработал и развернул идеальный программный образ (и BIOS). Однако реальность была иной. Модули продолжали сбоить. Иногда они восстанавливались после перезагрузки, иногда нет. Однако после восстановления модуля его нужно было протестировать.

Надо же. Ситуация становилась странной.

Странности продолжались, и наконец я решил засучить рукава. Мне повезло найти очень терпеливого и отзывчивого реселлера, который оставался со мной на телефоне три часа, пока я собирал данные. На той клиентской точке по какой-то причине Ethernet-контроллер мог упасть при передаче по сети голосового трафика.

Остановлюсь на этом подробнее. Когда я говорю, что Ethernet-контроллер мог упасть, это означает, что он МОГ УПАСТЬ. Система и Ethernet-интерфейс выглядели нормально, а после передачи случайного количества трафика интерфейс мог сообщить об аппаратной ошибке (потеря связи с PHY) и терял соединение. Светодиоды на свиче и интерфейсе буквальным образом гасли. Контроллер был мёртв.

Вернуть его к жизни можно было, только если выключить и включить питание. Попытка перезагрузки модуля ядра или машины приводила к ошибке сканирования PCI. Интерфейс оставался мёртвым, пока машину физически не отключишь от розетки и включишь вновь. В большинстве случаев, для наших клиентов это означало необходимость снять оборудование.

Во время отладки с помощью этого очень терпеливого реселлера я заметил прекращение получения пакетов при падении интерфейса. В конце концов я определил закономерность: последним пакетом от интерфейса всегда был 100 Trying provisional response, и у него всегда была определённая длина. Также я отследил этот (Asterisk) ответ до INVITE, разработанного производителем телефонов.

Я позвонил реселлеру, собрал людей и продемонстрировал улики. Хотя был вечер пятницы, все приняли участие в работе и собрали тестовый стенд из нашего нового оборудования и телефонов этого производителя.

Сели в конференц-зале и начали набирать номера с максимальной быстротой, на какую были способны наши пальцы. Выяснилось, что мы можем воспроизвести проблему! Не при каждом звонке и не на каждом устройстве, но периодически нам удавалось положить Ethernet-контроллер, а периодически нет. Сбросив питание, мы пытались снова, и у нас получалось. В любом случае, как знает каждый, кто пытался диагностировать технические проблемы, первый шаг это воспроизведение проблемы. Нам это, наконец-то, удалось.

Поверьте, на это ушло много времени. Я знаю, как работает стэк OSI. Я знаю, как сегментировано ПО. Я знаю, что содержимое SIP-пакетов не должно влиять на Ethernet-адаптер. Это всё ерунда какая-то.

Наконец нам удалось изолировать проблему пакетов на отрезке между их приходом в наше устройство и на порте зеркалирования в свиче. Похоже, что мы получали INVITE, а не отправленный 100 Trying! Порт зеркалирования не получал от сети 100 Trying.

Нужно было разобраться с этим INVITE. Может быть, проблема была связана с обработкой этого пакета демоном пользовательского пространства (userspace daemon)? Может быть, проблема была в передаче 100 Trying? Один из коллег предложил закрыть SIP-приложение и посмотреть, сохранится ли проблема. Без этого приложения пакеты 100 Trying не передавались.

Нужно было как-то улучшить передачу проблемных пакетов. Мы изолировали передаваемый с телефона пакет INVITE и проиграть его с помощью tcpreplay. Это сработало. Впервые за несколько месяцев мы смогли по команде уронить порты с помощью одного пакета. Это был значительный прогресс, и пора было идти домой, то есть повторить тестовый стенд в домашней лаборатории!

Прежде, чем я продолжу рассказ, хочу рассказать о прекрасном open source-приложении, которое я нашёл. Ostinato превращает вас в пакетного ниндзя. Его возможности буквально безграничны. Без этого приложения я не смог бы продвинуться дальше.

Вооружившись этим швейцарским ножом для пакетов, я начал экспериментировать. Меня поразило то, что я обнаружил.

Всё начиналось со странной SIP/SDP-причуды. Взгляните на этот SDP:

v=0o=- 20047 20047 IN IP4 10.41.22.248s=SDP datac=IN IP4 10.41.22.248t=0 0m=audio 11786 RTP/AVP 18 0 18 9 9 101a=rtpmap:18 G729/8000a=fmtp:18 annexb=noa=rtpmap:0 PCMU/8000a=rtpmap:18 G729/8000a=fmtp:18 annexb=noa=rtpmap:9 G722/8000a=rtpmap:9 G722/8000a=fmtp:101 0-15a=rtpmap:101 telephone-event/8000a=ptime:20a=sendrecv

Да, всё верно. Предложение о передаче звука дублируется. Это проблема, но повторюсь, какое отношение имеет к этому Ethernet-контроллер?! Ну, не считая того, что больше ничто другое не увеличивает размер Ethernet-фрейма Но подождите, в передаваемых пакетах было много успешных Ethernet-фреймов. Какие-то из них были меньше, какие-то больше. С ними проблем не было. Пришлось копать дальше. После нескольких приёмов кунг-фу с помощью Ostinato и кучи переподключений электричества я смог выявить проблемную взаимосвязь (с проблемным фреймом). Внимание: мы будем рассматривать шестнадцатеричные значения.

Падение интерфейса инициировалось определённым значением байта с определённым смещением: шестнадцатеричное значение 32 (в ASCII это 2) с 0x47f. Угадайте, откуда взялось 2.

a=ptime:20

Все наши SDP были идентичны (включая ptime). Все исходные и конечные URI были идентичны. Единственным отличием были ID вызовов, тэги и ветки (branches). Проблемные пакеты имели такое сочетание ID вызова, тэгов и веток, при котором в ptime получалось значение 2 со смещением 0x47f.

Вот так! С правильными ID, тэгами и ветками (или любым случайным мусором) хороший пакет мог превратиться в пакет-убийцу, как только строка ptime заканчивалась на определённом адресе. Это было очень странно.

При генерировании пакетов я поэкспериментировал с разными шестнадцатеричными значениями. Ситуация оказалась ещё запутанней. Выяснилось, что поведение контроллера целиком зависело от этого конкретного значения, находящегося по указанном адресу в первом полученном пакете. Картина была такая:

Байт 0x47f = 31 HEX (1 ASCII) - Никакого эффектаБайт 0x47f = 32 HEX (2 ASCII) - Интерфейс падаетБайт 0x47f = 33 HEX (3 ASCII) - Интерфейс падаетБайт 0x47f = 34 HEX (4 ASCII) - Трансформирование (inoculation) интерфейса

Когда я говорил не влияет, я имел в виду не только не убивает интерфейс, но и не трансформирует (более или менее). А когда я говорю, что интерфейс падает, ну, помните моё описание? Интерфейс умирает. Напрочь.

После новых тестов я выяснил, что проблема сохраняется с каждой версией Linux, которую мне удалось найти, с FreeBSD, и даже при включении машины без загрузочного носителя! Дело было в оборудовании, а не в ОС. Ого.

Более того, с помощью Ostinato я смог создать разные версии пакета-убийцы: HTTP POST, ICMP echo-запрос и другие. Почти всё, что я хотел. С помощью модифицированного HTTP-сервера, который генерировал данные в байтовых значениях (на основе заголовков, хоста и т.д.), можно было легко создать 200-й HTTP-запрос, чтобы тот содержал пакет смерти и убивал клиентские машины за файрволом!

Я уже объяснял, насколько странной была вся ситуация. Но самым странным было трансформирование. Оказалось, что если первый полученный пакет содержал любое значение (из опробованных мной), за исключением 1, 2 или 3, тогда интерфейс становился неуязвимым для любых пакетов смерти (содержавших значения 2 или 3). Более того, валидные атрибуты ptime были кратными 10: 10, 20, 30, 40. В зависимости от сочетания ID вызова, тэга, ветки, IP, URI и прочего (с этим забагованным SDP), эти валидные атрибуты ptime выстраивались в идеальную последовательность. Каковы были шансы на это?!

Внезапно стало ясно, почему проблема возникала спорадически. Удивительно, что мне удалось это выяснить. Я 15 лет работаю с сетями и не встречал ничего подобного. И сомневаюсь, что встречу опять. Надеюсь

Я связался с двумя инженерами в Intel и отправил им демо, чтобы они могли воспроизвести проблему. Поэкспериментировав пару недель, они выяснили, что проблема была связана с EEPROM в контроллерах 82574L. Они прислали мне новую EEPROM и инструмент для записи. К сожалению, мы не могли его распространять, к тому же требовалось выгружать и перезагружать модуль ядра e1000e, поэтому инструмент не подходил для нашего окружения. К счастью (немного зная схему EEPROM) я смог написать bash-скрипт, а затем с помощью магии ethtool сохранил исправленные значения и прописал их в системах, где проявлялся баг. Теперь мы могли выявлять проблемные аппараты. Мы связались с нашим вендором, чтобы тот применил исправление ко всем устройствам, прежде чем отгружать нам. Неизвестно только, сколько таких Ethernet-контроллеров Intel уже было продано.

На одну паллету больше


В 2005-м у меня на работе была необъяснимая проблема. Через день после незапланированного закрытия (из-за урагана) я начал получать звонки от пользователей, которые жаловались на таймауты при подключении к базе данных. Поскольку у нас была очень простая сеть на 32 ноды и с практически неиспользуемой пропускной способностью, меня напугало, что можно было 15-20 минут пинговать сервер с БД, а потом примерно две минуты получать request timed out. Я запустил на этом сервере мониторинг производительности и прочие инструменты, и начал пинговать его из разных мест. За исключением сервера, остальные машины всё время могли общаться с другими участниками сети. Я искал сбойный свич или соединение, но не мог найти объяснение случайным и периодическим сбоям.

Я попросил коллегу понаблюдать за светодиодами на свиче, расположенном на складе, пока я занимался трассировкой и переподключал разные устройства. Прошло 45-50 минут, коллега сообщал мне по рации этот выключен, тот поднялся. Я спросил, не заметил ли он какой-то закономерности.

Да заметил. Но ты подумаешь, что я чокнутый. Каждый раз, когда погрузчик вывозит паллету из отгрузочного зала, на сервере возникает таймаут в две секунды.

ЧТО???

Ага. И сервер восстанавливается, когда погрузчик начинает отгружать новый заказ.

Я прибежал посмотреть на погрузчик и был уверен, что он отмечает успешное завершение заказа включением какого-нибудь гигантского магнетрона. Несомненно, электромагнитные волны от конденсатора приводят к разрыву пространственно-временного континуума и временно прерывают работу серверной NIC-карты, находящейся в другой комнате в 50 метрах. Нет. Погрузчик просто ставил на паллету более крупные коробки, сверху коробки поменьше, при этом сканируя каждую коробку беспроводным сканером штрих-кодов. Ага! Наверное, это сканер обращается к серверу базы данных, что приводит к сбою других запросов. Неа. Я проверил и выяснил, что сканер тут ни при чём. Беспроводной маршрутизатор и его ИБП в отгрузочном зале были сконфигурированы правильно и функционировали нормально. Причина была в чём-то другом, ведь до закрытия из-за урагана всё прекрасно работало.

Как только начался следующий таймаут, я прибежал в отгрузочный зал и наблюдал, как грузчик наполняет следующую паллету. Едва он поставил четыре большие коробки шампуня на пустой поддон, сервер снова стал недоступен! Я не верил в абсурдность происходящего и ещё пять минут снимал и ставил коробки шампуня, с тем же результатом. Я уже готов был пасть на колени и молить о милосердии Бога Интранета, когда заметил, маршрутизатор в отгрузочном зале висит примерно на 30 см ниже уровня коробок, стоявших на паллете. Есть зацепка!

Когда на паллету ставили большие коробки, у беспроводного маршрутизатора пропадала прямая видимость с внешним складом. Через десять минут я решил проблему. Вот что произошло. Во время урагана был сбой в электросети, из-за которого сбросилось единственное устройство, не подключённое к ИБП тестовый беспроводной маршрутизатор в моём офисе. Настройки по умолчанию почему-то превратили его в репитер для единственного другого беспроводного маршрутизатора, висевшего в отгрузочном зале. Оба устройства могли общаться друг с другом только тогда, когда между ними не было паллеты, но даже в этом случае сигнал не был слишком сильным. Когда маршрутизаторы общались, они создавали петлю в моей маленькой сети, и тогда все остальные пакеты к серверу БД терялись. У сервера был свой свич от основного маршрутизатора, поэтому как узел сети он находился гораздо дальше. Большинство других компьютеров висело на том же 16-портовом свиче, так что я без проблем пинговался между ними.

Я за одну секунду решил проблему, над которой мучился четыре часа: отключил питание у тестового маршрутизатора. Больше таймаутов на сервере не было.

Как в фильме Tron, только на компьютере Apple IIgs


В детстве одним из моих любимых фильмов был Tron, снятый в начале 1980-х. В нём рассказывалось о программисте, который оцифровался и был поглощён компьютерным миром, населённым персонифицированными программами. Протагонист присоединился к группе сопротивления в попытке свергнуть угнетателя Master Control Program (MCP), взбунтовавшуюся программу, которая эволюционировала, обрела жажду власти и попыталась захватить компьютерную систему Пентагона.

В одной из самых впечатляющих сцен программы-персонажи устраивают гонки на светоциклах двухколёсных машинах, похожих на мотоциклы, оставлявших позади себя стены. Один из протагонистов заставил вражеский пепелац врезаться в стену на арене, проделав сквозную дыру. Герои расправились с противниками и сбежали через дыру на свободу первый шаг на пути к свержению МСР.

Когда я смотрел фильм, даже не представлял, что годы спустя нечаянно воссоздам на компьютере Apple IIgs мир Tron, взбунтовавшихся программ и всего прочего.

Вот как это произошло. Когда я начал учиться программированию, я решил создать игру со светоциклами из Tron. Вместе со своим другом Марко я на Apple IIgs писал программу на ORCA/Pascal и ассемблере 65816. Во время игры экран закрашивался чёрным цветом с белой окантовкой. Каждая линия представляет одного из игроков. Мы отображали игровые баллы в строке в нижней части экрана. Графически это была не самая продвинутая программа, но зато простая и весёлая. Выглядела она так:


Игра поддерживала до четырёх игроков, если бы те могли усесться перед одной клавиатурой. Было неудобно, но работало. Нам редко удавалось собрать нужное количество людей, чтобы задействовать все четыре светоцикла, поэтому Марко добавил управляемых компьютеров игроков, которые могли составить разумную конкуренцию.

Гонка вооружений


Игра уже была очень забавной, но нам захотелось экспериментов. Мы добавили ракеты, чтобы у игроков был шанс спастись от неминуемой аварии. Как позднее описывал Марко:

У людей и ИИ было по три ракеты, которые можно было использовать в течение игры. Когда ракета попадала в стену, возникал взрыв, фон которого закрашивался чёрным, тем самым удалялись секции следа, оставленного предыдущими светоциклами.


Вскоре игроки и компьютеры могли ракетами прокладывать себе выход из трудных ситуаций. Хотя Tron-пуристы усмехнутся на это, ведь у программ в фильме не было такой роскоши, как ракеты.

Побег


Как и все необычные и причудливые события, это было ещё и неожиданное.

Однажды, когда мы с Марко играли против двух компьютерных игроков, мы загнали один из ИИ-циклов в ловушку между его собственной стеной и нижней границей экрана. Предвидя неминуемую аварию, он выстрелил ракетой, как и всегда до этого. Но в этот раз вместо стены он выстрелил в границу экрана, которая выглядела как след одного из светоциклов. Ракета попала в границу, оставила дыру размером со светоцикл, и компьютер незамедлительно покинул через неё игровое поле. Мы в замешательстве уставились на светоцикл, который проехал через строку с баллами. Он легко избегнул столкновения с символами, а затем вообще уехал с экрана.

И сразу после этого система упала.


Наш разум пошатнулся, когда мы попытались осознать произошедшее. Компьютер нашёл способ выбраться из игры. Когда светоцикл покинул экран, он сбежал в компьютерную память, совсем как в фильме. У нас отвисли челюсти, когда мы поняли, что произошло.

Что мы сделали, когда обнаружили дефект в нашей программе, который мог методически рушить всю систему? Мы повторили всё вновь. Сначала попробовали сами выбраться за пределы. Затем снова заставили компьютер сбежать. Каждый раз наградой нам были фантастические падения системы. Иногда лампочка дисковода моргала, когда накопитель бесконечно кряхтел. В другие разы экран заполнялся бессмысленными символами, или динамик издавал вопль или низкое гудение. А иногда всё это происходило сразу, и компьютер оказывался в состоянии полного раздрая.

Почему так происходило? Чтобы разобраться в этом, давайте рассмотрим архитектуру компьютера Apple IIgs.

(Не)защищённая память


Операционная система Apple IIgs не имела защищённой памяти, появившейся в более поздних ОС, когда области памяти назначались программа и защищались от доступа извне. Поэтому программа под Apple IIgs могла читать и писать всё, что угодно (за исключением ПЗУ). Для доступа к устройствам вроде дисковода IIgs использовал операции ввода-вывода с привязкой к памяти, поэтому можно было активировать дисковод, прочитав из определённой области памяти. Такая архитектура позволяла графическим программам читать и писать прямо в память экрана.

В игре использовался один из графических режимов Apple IIgs Super Hi-Res: восхитительное 320x200 пикселей с палитрой из 16 цветов. Для выбора палитры программист задавал 16 записей (пронумерованных от 0 до 15 или от $0 до F в шестнадцатеричном формате) для 12-битных значений цветов. Для рисования на экране можно было читать и писать цвета прямо в видеопамять.

Алгоритм определения сбоя


Мы воспользовались этой особенностью и реализовали определитель сбоя, считывая прямо из видеопамяти. Игра вычисляла для каждого светоцикла его следующую позицию на основе текущего направления, и считывала этот пиксель из видеопамяти. Если позиция была пустой, то есть представлена чёрным пикселем (запись в палитре $0), тогда игра продолжалась. Но если позиция была занята, игрок врезался в светоцикл или белую рамку экрана (запись в палитре 15 или $F). Пример:


Здесь показан верхний левый угол экрана. Цвет $F обозначает белую рамку, а цветовая запись $1 обозначает зелёный светоцикл игрока. Он движется влево, как показано стрелкой, то есть следующий пиксель пуст, его цвет $0. Если игрок продолжит двигаться в этом направлении более одного хода, он может столкнуться со стеной (цвет $F) и разбиться.

Выход за пределы


Алгоритм определения следующего пикселя с помощью ассемблерной математики быстро вычислял адрес в памяти одного пикселя выше, ниже, слева или справа от текущего пикселя. Поскольку любой пиксель на экране представлял собой адрес в памяти, алгоритм просто вычислял новый адрес, который нужно прочитать. И когда светоцикл покидал экран, алгоритм определял место в системной памяти для проверки столкновения со стеной. Это означало, что светоцикл теперь путешествовал по системной памяти, бессмысленно включая биты и врезаясь в память.

Запись в случайные ячейки системной памяти нельзя назвать мудрым архитектурным решением. Неудивительно, что игра из-за этого падала. Игрок-человек не будет ездить вслепую и обычно сразу врезается, что ограничивает масштабы проблем в системе. А у ИИ такой слабости нет. Компьютер мгновенно сканирует позиции вокруг себя, чтобы определить, врежется ли он в стену, и меняет своё направление. То есть, по мнению компьютера системная память ничем не отличалась от экранной памяти. Как описывал Марко:

Мы могли только гадать, что делает алгоритм, покидая экранную память. Очевидно, что он искал способ продолжить движение в направлении, у которого были значения 0. Если бы алгоритм попал в тупик и врезался в стену из чисел, он умер бы. Но иногда в таких ситуациях он оставался живым, пока в какой-то момент не перезаписывал своим следом какой-нибудь исполняющийся код, или пока не обращался к памяти, привязанной к устройству и тогда система падала. Но случалось это не сразу же после выхода за пределы экрана, ИИ какое-то время ещё бегал, пока не рушил систему.

В результате мы не только воссоздали гонку на светоциклах из фильма, но и сам побег. Как и в фильме, побег имел большие последствия.

Сегодня такое трудно повторить, поскольку операционные системы обзавелись защищённой памятью. Но я всё ещё гадаю, существуют ли программы как в Tron, которые пытаются выбраться из своих защищённых пространств в попытке помешать мятежному ИИ-коду захватить Пентагон.

Полагаю, чтобы это выяснить, нам нужно дождаться изобретения оцифровки сознания.

Сесть, чтобы залогиниться


Каждый программист знает, что отлаживать тяжело. Хотя у отличных отладчиков работа выглядит обманчиво простой. Обезумевшие программисты описывают баг, который они часами вылавливают, мастер задаёт несколько вопросов, и через несколько минут программисты видят перед собой сбойный код. Отладчик-эксперт не забывает, что всегда есть логическое объяснение, вне зависимости от того, насколько таинственно ведёт себя система на первый взгляд.

Такое отношение проиллюстрировано анекдотом, появившимся в исследовательском центре IBM Yorktown Heights. Программист недавно установил новую рабочую станцию. Всё было прекрасно, когда он сидел перед компьютером, но он не мог залогиниться, пока стоял. Это поведение воспроизводилось всегда: сидя программист залогинивался всегда, стоя не смог ни разу.

Многие из нас просто сидели и удивлялись. Откуда компьютер мог знать, стоят ли перед ним или сидят? Однако хорошие отладчики знают, что должна быть причина. Первое, что приходит в голову электричество. Надорванный провод под ковром, или статический заряд? Но проблемы, связанные с электричеством, редко воспроизводятся в 100 % случаев. Один из коллег наконец задал правильный вопрос: каким образом программист логинился сидя и стоя? Попробуйте сами.

Причина была в клавиатуре: две кнопки поменяны местами. Когда программист сидел, он набирал вслепую, и проблема оставалась незамеченной. А когда он стоял, это его сбивало с толку, он выискивал кнопки и нажимал их. Вооружившись этой подсказкой и отвёрткой, отладчик-эксперт поменял кнопки местами и всё наладилось.

Банковская система, развёрнутая в Чикаго, много месяцев работала нормально. Но неожиданно завершила работу, когда её впервые применили для обработки международных данных. Программисты днями ковыряли код, но не могли найти ни одной команды, которая приводила к завершению программы. Когда они внимательнее понаблюдали за её поведением, то обнаружили, что программа завершалась, если в неё вводили данные по Эквадору. Анализ показал, что когда пользователь печатал название столицы (Quito), программа интерпретировала это как команду завершения!

Однажды Боб Мартин встретил систему, работавшую один раз дважды. Она корректно обрабатывала первую транзакцию, а во всех последующих транзакциях возникали небольшие проблемы. Когда систему перезагрузили, она опять корректно обработала первую транзакцию и засбоила на всех последующих. Когда Боб охарактеризовал это поведение как работавшая один раз дважды, разработчики немедленно поняли, что нужно было искать переменную, которая корректно инициализировалась при загрузке программы, но не сбрасывалась после первой транзакции. Во всех случаях правильные вопросы позволяли мудрым программистам в кратчайшие сроки выявить неприятные ошибки: Что ты делал иначе, когда стоял и сидел? Покажи, как ты логинишься в обоих случаях, Что именно ты вводил перед завершением программы? Программа работала правильно, прежде чем начались сбои? Сколько раз?

Рик Лемонс сказал, что лучший урок, связанный с отладкой, он получил, когда наблюдал представление фокусника. Тот проделал пяток невозможных трюков, и Лемонс почувствовал, что верит в это. Затем он напомнил себе, что невозможное не является возможным, и проверил каждый трюк, чтобы доказать это очевидное несоответствие. Лемонс начал с того, что было непоколебимой истиной с законов физики, и исходя из них он начал искать простые объяснения каждому трюку. Такое отношение делает Лемонса одним из лучших отладчиков, что я встречал.

На мой взгляд, лучшая книга по отладке это The Medical Detectives, написанная Berton Roueche и опубликованная Penguin в 1991-м. Герои книги отлаживают сложные системы, от умеренно больного человека до очень больных городов. Применяемые там методы решения проблем можно напрямую использовать в отладке компьютерных систем. Эти реальные истории завораживают не меньше, чем любая выдумка.

Случай с 500-мильным email


Вот ситуация, которая звучала немыслимо Я почти отказался рассказывать о ней, потому что это отличная байка для конференций. Я слегка подкорректировал историю, чтобы защитить виновных, отбросить несущественные и скучные подробности, и в целом сделать повествование увлекательнее.

Несколько лет назад я обслуживал систему электронной почты в кампусе. Мне позвонил руководитель департамента статистики.

У нас проблема с отправкой писем.

Какая проблема?

Мы не можем отправлять письма дальше, чем на 500 миль.

Я подавился кофе.

Не понял.

Мы не можем отправлять из департамента письма дальше, чем на 500 миль. На самом деле, чуть дальше. Примерно 520 миль. Но это предел.

Хм Вообще-то электронная почта работает не так, ответил я, пытаясь совладать с паникой в голосе. Нельзя проявлять панику в разговоре с руководителем департамента, даже такого, как департамент статистики. Почему вы решили, что не можете отправлять письма дальше, чем на 500 миль?

Я не решил, веско ответил он. Видите ли, когда мы заметили происходящее, несколько дней назад

Вы ждали несколько ДНЕЙ? оборвал его я дрогнувшим голосом. И вы не могли отправлять письма всё это время?

Мы могли отправлять. Просто не дальше

Пятисот миль, да, закончил за него я. Понятно. Но почему вы раньше не позвонили?

Ну, до этого момента у нас не было достаточно данных, чтобы удостовериться в происходящем.

Точно, это же руководитель статистики.

В любом случае, я попросил одного из геостатистиков поработать с этим

Геостатистиков

Да, и она составила карту, показывающую радиус, внутри которого мы можем отправлять письма, чуть больше 500 миль. В этой зоне есть несколько мест, в которые наши письма не приходят совсем или периодически, но за пределы радиуса мы вообще не можем ничего отправить.

Понятно, сказал я и опустил голову на руки. Когда это началось? Вы сказали, что несколько дней назад, но мы ничего не меняли в ваших системах.

Приходил консультант, пропатчил и перезагрузил наш сервер. Но это я его вызывал, и он сказал, что не трогал почтовую систему.

Ладно, давайте я посмотрю и перезвоню вам, ответил я, с трудом веря, что участвую в подобном. Сегодня было не первое апреля. Я попытался вспомнить, не задолжал ли мне кто-нибудь розыгрыш.

Я залогинился на сервер их департамента и отправил несколько проверочных писем. Это происходило в Исследовательском Треугольнике Северной Каролины, и письмо в мой ящик пришло без проблем. Как и письма, отправленные в Ричмонд, Атланту и Вашингтон. Пришло и письмо, отправленное в Принстон (400 миль).

Но затем я отправил письмо в Мемфис (600 миль). Оно не пришло. В Бостон, не пришло. В Детройт, не пришло. Я достал адресную книгу и начал рассылать по ней письма. В Нью-Йорк (420 миль) пришло, а в Провиденс (580 миль) не пришло.

Я начал сомневаться в своём рассудке. Написал другу в Северной Каролине, провайдер которого был в Сиэтле. К счастью, письмо не пришло. Если бы проблема была связана с местоположением получателей, а не их почтовых серверов, наверное, я разрыдался бы.

Выяснив, что проблема действительно существует (невероятно) и воспроизводима, я начал анализировать файл sendmail.cf. Он выглядел нормально. Привычно. Я сравнил его с sendmail.cf в моей домашней директории. Разницы не было это был файл, который я написал. И я был уверен, что не включал опцию FAIL_MAIL_OVER_500_MILES. В растерянности я с помощью telnet прозвонил SMTP-порт. Сервер радостно ответил баннером Sendmail из SunOS.

Погодите баннер Sendmail из SunOS? В то время Sun ещё поставляла Sendmail 5 со своей операционной системой, хотя Sendmail 8 была уже вполне допилена. Поскольку я был хорошим сисадмином, я ввёл Sendmail 8 в качестве стандарта. Кроме того, поскольку я был хорошим сисадмином, я написал sendmail.cf, в котором использовались классные длинные самодокументируемые опции и имена переменных, доступные в Sendmail 8, а не загадочные коды из знаков препинания, применявшиеся в Sendmail 5.

Всё встало на свои места, и я опять подавился своим уже остывшим кофе. Похоже, когда консультант пропатчил сервер, он обновил версию SunOS, с которой накатил более старую версию Sendmail. К счастью, файл sendmail.cf сохранился, но теперь он не подходил.

Оказалось, что Sendmail 5 по крайней мере, поставляемая Sun версия, имевшая ряд улучшений может работать с sendmail.cf для Sendmail 8, потому что большинство правил остались теми же. Но новые длинные опции конфигурации теперь не распознавались и отбрасывались. И поскольку для большинства из них в бинарнике Sendmail не было значений по умолчанию, программа не находила в sendmail.cf подходящих значений и сбрасывала их на ноль.

Одним из таких обнулённых значений был таймаут подключения к удалённому SMTP-серверу. После экспериментов выяснилось, что на этой конкретной машине при обычной нагрузке нулевой таймаут приводит к разрыву подключения чуть больше, чем через три миллисекунды.

В то время сеть кампуса была полностью построена на свичах. Исходящий пакет не задерживался, пока через протокол POP не попадал на маршрутизатор на другой стороне. То есть длительность подключения к слабонагруженному удалённому хосту в соседней сети по большей части зависела от расстояния, которое покрывалось со скоростью света, а не от случайных задержек маршрутизаторами.

Чувствуя лёгкое головокружение, я ввёл в командной строке:

$ units1311 units, 63 prefixesYou have: 3 millilightsecondsYou want: miles        * 558.84719        / 0.0017893979

500 миль или чуть больше.



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

Перевод Фольклор программистов и инженеров (часть 3)

24.08.2020 10:10:39 | Автор: admin


Последняя часть подборки историй из интернета о том, как у багов иногда бывают совершенно невероятные проявления. Первая часть, вторая часть.

Маленький SSH, который (иногда) не мог


Это рассказ об одной из самых увлекательных охот на баг, в которой мне посчастливилось участвовать.

В компании AdGear Technologies Inc., где я работал, королём был SSH. Мы применяли его для управления, мониторинга, развёртывания, сбора журналов, даже для потокового вещания в реальном времени. Этот протокол устойчивый и надёжный, обладает предсказуемостью нативного Unix-инструмента и просто работает.

Но однажды случайные Cron-письма подсказали нам, что протокол не работает.

Таймаут


На машинах в нашем лондонском ЦОДе возникали случайные сбои при отправке файлов журналов в ЦОД в Монреале. Эта задача периодически запускалась из Cron, и сбой проявлялся так:

  • Cron-письма сообщали о проблемах с SSH.
    • Иногда он зависает.
    • Иногда завершается без ошибки по таймауту.
  • При внутренней проверке работоспособности Nagios предупреждает об отсутствующих данных в Монреале.

Мы залогинились на лондонские машины, вручную запустили команду push и она успешно отработала. Мы списали это на временные сетевые неполадки.

Таймауты


Но сбои продолжали случайным образом повторяться. Раз в день, пару раз в день, утром в пятницу, несколько раз в час. Было понятно, что становится хуже. Мы продолжали вручную пушить файлы, пока не поняли, в чём заключается проблема.

Между Лондоном и Монреалем было 17 хопов. Мы создали профиль задержек и потерь пакетов. Оказалось, что на паре хопов терялось 1-3 % пакетов. Вместе с отделом эксплуатации лондонского ЦОДа мы заявку на перемаршрутизацию.

Пока лондонцы проверяли информацию о потере пакетов, мы начали искать случайные таймауты на пути от Лондона до нашего второго ЦОДа в Монреале. Хопы на этом маршруте были другие, не те, на которых терялись пакеты. Мы решили, что потеря не главная проблема, к тому же лондонцы сообщили, что не могут воспроизвести потерю пакетов или таймауты, и что на их стороне всё выглядит нормально.

Апокалипсис


Пересылая вручную сбойные Cron-письма, мы заметили интересную закономерность. Файлы либо успешно передавались на большой скорости, либо вообще не передавались и зависали по таймауту. Не было случаев, чтобы файлы успешно загружались на низкой скорости.

Убрав из уравнения большую часть данных, мы смогли воссоздать сценарий с помощью простого ванильного SSH. В лондонском ЦОДе сервер SSH mtl-machine либо моментально выполнял задачу, либо повисал и не мог установить соединение. Удивление начало расти.

Куда делись пакеты?


Мы трижды проверили конфигурацию SSH-севера и работу систем в Монреале:

  • DNS-серверы отвечали быстро.
  • Зона обратного просмотра DNS была отключена.
  • Максимальное количество клиентских подключений было достаточно велико.
  • Нас не атаковали.
  • Канал не был забит.

Кроме того, даже если что-то не работало, мы наблюдали бы зависания при работе с двумя разными ЦОДами в Монреале. Причём наши нелондонские ЦОДы успешно общались с Монреалем. То есть проблема была связана с Лондоном.

Мы запустили tcpdump и стали наблюдать за пакетами. Нас интересовала общая динамика и данные, полученные с помощью Pcaps и загруженные в Wireshark. Мы увидели признаки потери пакетов и повторной отправки, но всё было на минимальном уровне и вызывало беспокойства.

Затем мы целиком проанализировали подключения в ситуациях, когда связь по SSH устанавливалась успешно, а затем подключения в ситуациях, когда связь по SSH зависала.

Когда подключение из Лондона к Монреалю зависло, мы пришли к таким выводам:

  • Установка связи по TCP прошла нормально.
  • Туда-обратно была передана служебная SSH-информация. Где нужно, были нормальные TCP ack-пакеты.
  • Определённый пакет был отправлен из Лондона и получен в Монреале.
  • Тот же пакет был несколько раз заново отправлен из Лондона и получен в Монреале.
  • Просто Монреаль на это не отвечает!

Было непонятно, почему не отвечает Монреаль (из-за этого Лондон отправляет данные заново). На этом соединение зависло, потому что завис протокол 4 уровня. Ещё более волнительным было то, что если в Лондоне прервать повторную SSH-отправку и сразу же её перезапустить, то она успешно отработает. В этом случае tcpdump показывал, что Монреаль получил пакет и ответил на это, и работа продолжалась.

На SSH-клиенте в Лондоне мы включили подробную отладку (-vvv), и после этих записей в журнале связь повисла:

debug2: kex_parse_kexinit: first_kex_follows 0 debug2: kex_parse_kexinit: reserved 0 debug2: mac_setup: found hmac-md5debug1: kex: server->client aes128-ctr hmac-md5 nonedebug2: mac_setup: found hmac-md5debug1: kex: client->server aes128-ctr hmac-md5 nonedebug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sentdebug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP

Мы погуглили по запросу SSH hang SSH2_MSG_KEX_DH_GEX_GROUP и получили много результатов: от проблем с Wi-Fi до TCPбагов в Windows и глючных маршрутизаторов, теряющих TCP-фрагменты. В качестве одного из решений для LAN предлагалось вычислить MSS пути и задать это значение в качестве MTU на обоих концах маршрута.

Я продолжал уменьшать MTU на лондонском сервере с 1500 это не помогало до тех пор, пока я не дошёл до волшебного значения 576. После этого зависание SSH больше не повторялось. У меня исполнялся скрипт с SSH-циклом, и по желанию я мог вызвать таймауты, вернув MTU значение 1500, или избавиться от них, задав 576. К сожалению, это публичные рекламные серверы, и глобальное назначение MTU 1500 не решит проблемы. Однако выше уже упоминалось, что, вероятно, где-то сломан процесс фрагментации или пересборки пакетов.

Вернёмся к проверке полученных пакетов с помощью tcpdump: признаков фрагментации не было. Размер полученного пакета полностью соответствовал размеру отправленного. Если что-то фрагментировало пакет на байте 576+, то что-то успешно собирало его обратно.

Мерцай-мерцай, кривая звёздочка


Углубившись в анализ, я изучал полные дампы пакетов (tcpdump -s 0 -X), а не одни лишь заголовки. При сравнении волшебного пакета из успешной отправки с пакетом из сбойной отправки, я почти не нашёл различий, за исключением TCP/IP-заголовков. Но было очевидно, что это первый пакет в TCP-соединении, содержавший достаточно данных для прохода через отметку в 576 байтов. Все предыдущие пакеты были гораздо меньше.

Сравнив тот же пакет из сбойной отправки, в том виде, в каком он покинул Лондон и пришёл в Монреаль, мой взгляд за что-то зацепился. За что-то малозаметное, и я отмахнулся из-за усталости (был поздний вечер пятницы). Но после нескольких обновлений и сравнений мне уже не мерещилось.

Так выглядел пакет, покинувший Лондон (минус несколько первых байтов, идентифицирующих IP-адреса)
0x0040: 0b7c aecc 1774 b770 ad92 0000 00b7 6563 .|...t.p......ec
0x0050: 6468 2d73 6861 322d 6e69 7374 7032 3536 dh-sha2-nistp256
0x0060: 2c65 6364 682d 7368 6132 2d6e 6973 7470 ,ecdh-sha2-nistp
0x0070: 3338 342c 6563 6468 2d73 6861 322d 6e69 384,ecdh-sha2-ni
0x0080: 7374 7035 3231 2c64 6966 6669 652d 6865 stp521,diffie-he
0x0090: 6c6c 6d61 6e2d 6772 6f75 702d 6578 6368 llman-group-exch
0x00a0: 616e 6765 2d73 6861 3235 362c 6469 6666 ange-sha256,diff
0x00b0: 6965 2d68 656c 6c6d 616e 2d67 726f 7570 ie-hellman-group
0x00c0: 2d65 7863 6861 6e67 652d 7368 6131 2c64 -exchange-sha1,d
0x00d0: 6966 6669 652d 6865 6c6c 6d61 6e2d 6772 iffie-hellman-gr
0x00e0: 6f75 7031 342d 7368 6131 2c64 6966 6669 oup14-sha1,diffi
0x00f0: 652d 6865 6c6c 6d61 6e2d 6772 6f75 7031 e-hellman-group1
0x0100: 2d73 6861 3100 0000 2373 7368 2d72 7361 -sha1...#SSH-rsa
0x0110: 2c73 7368 2d64 7373 2c65 6364 7361 2d73 ,SSH-dss,ecdsa-s
0x0120: 6861 322d 6e69 7374 7032 3536 0000 009d ha2-nistp256
0x0130: 6165 7331 3238 2d63 7472 2c61 6573 3139 aes128-ctr,aes19
0x0140: 322d 6374 722c 6165 7332 3536 2d63 7472 2-ctr,aes256-ctr
0x0150: 2c61 7263 666f 7572 3235 362c 6172 6366 ,arcfour256,arcf
0x0160: 6f75 7231 3238 2c61 6573 3132 382d 6362 our128,aes128-cb
0x0170: 632c 3364 6573 2d63 6263 2c62 6c6f 7766 c,3des-cbc,blowf
0x0180: 6973 682d 6362 632c 6361 7374 3132 382d ish-cbc,cast128-
0x0190: 6362 632c 6165 7331 3932 2d63 6263 2c61 cbc,aes192-cbc,a
0x01a0: 6573 3235 362d 6362 632c 6172 6366 6f75 es256-cbc,arcfou
0x01b0: 722c 7269 6a6e 6461 656c 2d63 6263 406c r,rijndael-cbc@l
0x01c0: 7973 6174 6f72 2e6c 6975 2e73 6500 0000 ysator.liu.se
0x01d0: 9d61 6573 3132 382d 6374 722c 6165 7331 .aes128-ctr,aes1
0x01e0: 3932 2d63 7472 2c61 6573 3235 362d 6374 92-ctr,aes256-ct
0x01f0: 722c 6172 6366 6f75 7232 3536 2c61 7263 r,arcfour256,arc
0x0200: 666f 7572 3132 382c 6165 7331 3238 2d63 four128,aes128-c
0x0210: 6263 2c33 6465 732d 6362 632c 626c 6f77 bc,3des-cbc,blow
0x0220: 6669 7368 2d63 6263 2c63 6173 7431 3238 fish-cbc,cast128
0x0230: 2d63 6263 2c61 6573 3139 322d 6362 632c -cbc,aes192-cbc,
0x0240: 6165 7332 3536 2d63 6263 2c61 7263 666f aes256-cbc,arcfo
0x0250: 7572 2c72 696a 6e64 6165 6c2d 6362 6340 ur,rijndael-cbc@
0x0260: 6c79 7361 746f 722e 6c69 752e 7365 0000 lysator.liu.se
0x0270: 00a7 686d 6163 2d6d 6435 2c68 6d61 632d ..hmac-md5,hmac-
0x0280: 7368 6131 2c75 6d61 632d 3634 406f 7065 sha1,umac-64@ope
0x0290: 6e73 7368 2e63 6f6d 2c68 6d61 632d 7368 nSSH.com,hmac-sh
0x02a0: 6132 2d32 3536 2c68 6d61 632d 7368 6132 a2-256,hmac-sha2
0x02b0: 2d32 3536 2d39 362c 686d 6163 2d73 6861 -256-96,hmac-sha
0x02c0: 322d 3531 322c 686d 6163 2d73 6861 322d 2-512,hmac-sha2-
0x02d0: 3531 322d 3936 2c68 6d61 632d 7269 7065 512-96,hmac-ripe
0x02e0: 6d64 3136 302c 686d 6163 2d72 6970 656d md160,hmac-ripem
0x02f0: 6431 3630 406f 7065 6e73 7368 2e63 6f6d d160@openSSH.com
0x0300: 2c68 6d61 632d 7368 6131 2d39 362c 686d ,hmac-sha1-96,hm
0x0310: 6163 2d6d 6435 2d39 3600 0000 a768 6d61 ac-md5-96....hma
0x0320: 632d 6d64 352c 686d 6163 2d73 6861 312c c-md5,hmac-sha1,
0x0330: 756d 6163 2d36 3440 6f70 656e 7373 682e umac-64@openSSH.
0x0340: 636f 6d2c 686d 6163 2d73 6861 322d 3235 com,hmac-sha2-25
0x0350: 362c 686d 6163 2d73 6861 322d 3235 362d 6,hmac-sha2-256-
0x0360: 3936 2c68 6d61 632d 7368 6132 2d35 3132 96,hmac-sha2-512
0x0370: 2c68 6d61 632d 7368 6132 2d35 3132 2d39 ,hmac-sha2-512-9
0x0380: 362c 686d 6163 2d72 6970 656d 6431 3630 6,hmac-ripemd160
0x0390: 2c68 6d61 632d 7269 7065 6d64 3136 3040 ,hmac-ripemd160@
0x03a0: 6f70 656e 7373 682e 636f 6d2c 686d 6163 openSSH.com,hmac
0x03b0: 2d73 6861 312d 3936 2c68 6d61 632d 6d64 -sha1-96,hmac-md
0x03c0: 352d 3936 0000 0015 6e6f 6e65 2c7a 6c69 5-96....none,zli
0x03d0: 6240 6f70 656e 7373 682e 636f 6d00 0000 b@openSSH.com
0x03e0: 156e 6f6e 652c 7a6c 6962 406f 7065 6e73 .none,zlib@opens
0x03f0: 7368 2e63 6f6d 0000 0000 0000 0000 0000 sh.com
0x0400: 0000 0000 0000 0000 0000 0000

А так выглядел тот же пакет, пришедший в Монреаль
0x0040: 0b7c aecc 1774 b770 ad92 0000 00b7 6563 .|...t.p......ec
0x0050: 6468 2d73 6861 322d 6e69 7374 7032 3536 dh-sha2-nistp256
0x0060: 2c65 6364 682d 7368 6132 2d6e 6973 7470 ,ecdh-sha2-nistp
0x0070: 3338 342c 6563 6468 2d73 6861 322d 6e69 384,ecdh-sha2-ni
0x0080: 7374 7035 3231 2c64 6966 6669 652d 6865 stp521,diffie-he
0x0090: 6c6c 6d61 6e2d 6772 6f75 702d 6578 6368 llman-group-exch
0x00a0: 616e 6765 2d73 6861 3235 362c 6469 6666 ange-sha256,diff
0x00b0: 6965 2d68 656c 6c6d 616e 2d67 726f 7570 ie-hellman-group
0x00c0: 2d65 7863 6861 6e67 652d 7368 6131 2c64 -exchange-sha1,d
0x00d0: 6966 6669 652d 6865 6c6c 6d61 6e2d 6772 iffie-hellman-gr
0x00e0: 6f75 7031 342d 7368 6131 2c64 6966 6669 oup14-sha1,diffi
0x00f0: 652d 6865 6c6c 6d61 6e2d 6772 6f75 7031 e-hellman-group1
0x0100: 2d73 6861 3100 0000 2373 7368 2d72 7361 -sha1...#SSH-rsa
0x0110: 2c73 7368 2d64 7373 2c65 6364 7361 2d73 ,SSH-dss,ecdsa-s
0x0120: 6861 322d 6e69 7374 7032 3536 0000 009d ha2-nistp256
0x0130: 6165 7331 3238 2d63 7472 2c61 6573 3139 aes128-ctr,aes19
0x0140: 322d 6374 722c 6165 7332 3536 2d63 7472 2-ctr,aes256-ctr
0x0150: 2c61 7263 666f 7572 3235 362c 6172 6366 ,arcfour256,arcf
0x0160: 6f75 7231 3238 2c61 6573 3132 382d 6362 our128,aes128-cb
0x0170: 632c 3364 6573 2d63 6263 2c62 6c6f 7766 c,3des-cbc,blowf
0x0180: 6973 682d 6362 632c 6361 7374 3132 382d ish-cbc,cast128-
0x0190: 6362 632c 6165 7331 3932 2d63 6263 2c61 cbc,aes192-cbc,a
0x01a0: 6573 3235 362d 6362 632c 6172 6366 6f75 es256-cbc,arcfou
0x01b0: 722c 7269 6a6e 6461 656c 2d63 6263 406c r,rijndael-cbc@l
0x01c0: 7973 6174 6f72 2e6c 6975 2e73 6500 0000 ysator.liu.se
0x01d0: 9d61 6573 3132 382d 6374 722c 6165 7331 .aes128-ctr,aes1
0x01e0: 3932 2d63 7472 2c61 6573 3235 362d 6374 92-ctr,aes256-ct
0x01f0: 722c 6172 6366 6f75 7232 3536 2c61 7263 r,arcfour256,arc
0x0200: 666f 7572 3132 382c 6165 7331 3238 2d63 four128,aes128-c
0x0210: 6263 2c33 6465 732d 6362 632c 626c 6f77 bc,3des-cbc,blow
0x0220: 6669 7368 2d63 6263 2c63 6173 7431 3238 fish-cbc,cast128
0x0230: 2d63 6263 2c61 6573 3139 322d 6362 632c -cbc,aes192-cbc,
0x0240: 6165 7332 3536 2d63 6263 2c61 7263 666f aes256-cbc,arcfo
0x0250: 7572 2c72 696a 6e64 6165 6c2d 6362 7340 ur,rijndael-cbs@
0x0260: 6c79 7361 746f 722e 6c69 752e 7365 1000 lysator.liu.se
0x0270: 00a7 686d 6163 2d6d 6435 2c68 6d61 732d ..hmac-md5,hmas-
0x0280: 7368 6131 2c75 6d61 632d 3634 406f 7065 sha1,umac-64@ope
0x0290: 6e73 7368 2e63 6f6d 2c68 6d61 632d 7368 nSSH.com,hmac-sh
0x02a0: 6132 2d32 3536 2c68 6d61 632d 7368 7132 a2-256,hmac-shq2
0x02b0: 2d32 3536 2d39 362c 686d 6163 2d73 7861 -256-96,hmac-sxa
0x02c0: 322d 3531 322c 686d 6163 2d73 6861 322d 2-512,hmac-sha2-
0x02d0: 3531 322d 3936 2c68 6d61 632d 7269 7065 512-96,hmac-ripe
0x02e0: 6d64 3136 302c 686d 6163 2d72 6970 756d md160,hmac-ripum
0x02f0: 6431 3630 406f 7065 6e73 7368 2e63 7f6d d160@openSSH.c.m
0x0300: 2c68 6d61 632d 7368 6131 2d39 362c 786d ,hmac-sha1-96,xm
0x0310: 6163 2d6d 6435 2d39 3600 0000 a768 7d61 ac-md5-96....h}a
0x0320: 632d 6d64 352c 686d 6163 2d73 6861 312c c-md5,hmac-sha1,
0x0330: 756d 6163 2d36 3440 6f70 656e 7373 782e umac-64@openssx.
0x0340: 636f 6d2c 686d 6163 2d73 6861 322d 3235 com,hmac-sha2-25
0x0350: 362c 686d 6163 2d73 6861 322d 3235 362d 6,hmac-sha2-256-
0x0360: 3936 2c68 6d61 632d 7368 6132 2d35 3132 96,hmac-sha2-512
0x0370: 2c68 6d61 632d 7368 6132 2d35 3132 3d39 ,hmac-sha2-512=9
0x0380: 362c 686d 6163 2d72 6970 656d 6431 3630 6,hmac-ripemd160
0x0390: 2c68 6d61 632d 7269 7065 6d64 3136 3040 ,hmac-ripemd160@
0x03a0: 6f70 656e 7373 682e 636f 6d2c 686d 7163 openSSH.com,hmqc
0x03b0: 2d73 6861 312d 3936 2c68 6d61 632d 7d64 -sha1-96,hmac-}d
0x03c0: 352d 3936 0000 0015 6e6f 6e65 2c7a 7c69 5-96....none,z|i
0x03d0: 6240 6f70 656e 7373 682e 636f 6d00 0000 b@openSSH.com
0x03e0: 156e 6f6e 652c 7a6c 6962 406f 7065 6e73 .none,zlib@opens
0x03f0: 7368 2e63 6f6d 0000 0000 0000 0000 0000 sh.com
0x0400: 0000 0000 0000 0000 0000 0000

Что-нибудь заметили? Если нет, то ничего страшного. Можете скопировать в два окна в текстовом редакторе и быстро переключаться между ними, чтобы увидеть изменения символов.

Так-так. Это не потеря пакетов, а их повреждение! Очень небольшое, очень предсказуемое повреждение. Интересные наблюдения:

  • Начальная часть пакета (<576 байтов) не повреждена.
  • Повреждён каждый 15-й байт из 16.
  • Повреждение предсказуемое. Все h стали x, все c стали s.

Вы могли уже свериться с ASCII-таблицей и прийти к выводу: один бит застрял на значении 1. Превращение в 1 четвёртого бита в байте портит предыдущие буквы слева до значений справа.

Очевидные виновники в нашем поле зрения (NIC-карты, принимающие серверы) вне подозрений, потому что у сбоя есть закономерность (несколько лондонских машин несколько монреальских ЦОДов и машин). Причина должна быть на маршруте и ближе к Лондону.

Ситуация начала обретать смысл. Я также заметил маленькую подсказку в подробном режиме tcpdump (tcp cksum bad), которую раньше не замечал. Монреальский сервер отбрасывал пакет на уровне ядра, когда понимал, что тот повреждён, и не передавал пакет SSH-демону в пользовательском пространстве. Затем Лондон снова отправлял пакет, тот опять повреждался, а Монреаль молча его отбрасывал. С точки зрения SSH и SSHd, соединение зависло. С точки зрения tcpdump, потерь не было, а монреальские серверы просто игнорируют данные.

Мы сообщили о своих находках в отдел эксплуатации лондонского ЦОДа, и через несколько минут они сильно изменили исходящие маршруты. Первый хоп и большинство последующих были другими. Проблема зависания исчезла.

Фиксы поздней ночью в пятницу приятны, потому что на выходных можно расслабиться и не думать о проблемах и службе поддержки :)

Где Вальдо?


Радуясь, что мы больше не страдаем от этой проблемы и что наши системы навёрстывают отставание, я решил найти устройство, виновное в этом повреждении пакетов.

Обновление лондонских маршрутов, чтобы трафик не шёл по старому пути, означало, что я не смогу легко воспроизвести проблему. Я нашёл в Монреале друга с подходящей машиной под FreeBSD, которая была доступна из Лондона по старым маршрутам.

Я хотел убедиться в предсказуемости повреждения даже без участия SSH. Мне это легко удалось с помощью нескольких конвейеров.

В Монреале:

nc -l -p 4000 > /dev/null

Затем в Лондоне:

cat /dev/zero | nc mtl 4000

Учитывая фактор случайности и настройку в цикле повторных попыток, я получил несколько пакетов, которые развеяли все сомнения относительно предыдущих умозаключений. Вот часть одного из пакетов:

Мы отправляли просто пакет нулей
0x0210
0x0220 0000 0000 0000 0000 0000 0000 0000 0000
0x0230 0000 0000 0000 0000 0000 0000 0000 0000
0x0240 0000 0000 0000 0000 0000 0000 0000 0000
0x0250 0000 0000 0000 0000 0000 0000 0000 1000
0x0260 0000 0000 0000 0000 0000 0000 0000 1000
0x0270 0000 0000 0000 0000 0000 0000 0000 1000
0x0280 0000 0000 0000 0000 0000 0000 0000 1000
0x0290 0000 0000 0000 0000 0000 0000 0000 1000
0x02a0 0000 0000 0000 0000 0000 0000 0000 1000
0x02b0 0000 0000 0000 0000 0000 0000 0000 1000
0x02c0 0000 0000 0000 0000 0000 0000 0000 1000
0x02d0 0000 0000 0000 0000 0000 0000 0000 1000
0x02e0 0000 0000 0000 0000 0000 0000 0000 1000
0x02f0 0000 0000 0000 0000 0000 0000 0000 1000
0x0300 0000 0000 0000 0000 0000 0000 0000 1000
0x0310 0000 0000 0000 0000 0000 0000 0000 1000
0x0320 0000 0000 0000 0000 0000 0000 0000 1000
0x0330 0000 0000 0000 0000 0000 0000 0000 1000
0x0340 0000 0000 0000 0000 0000 0000 0000 1000
0x0350 0000 0000 0000 0000 0000 0000 0000 1000
0x0360 0000 0000 0000 0000 0000 0000 0000 1000
0x0370 0000 0000 0000 0000 0000 0000 0000 1000
0x0380 0000 0000 0000 0000 0000 0000 0000 1000
0x0390 0000 0000 0000 0000 0000 0000 0000 1000
0x03a0 0000 0000 0000 0000 0000 0000 0000 1000
0x03b0 0000 0000 0000 0000 0000 0000 0000 1000
0x03c0 0000 0000 0000 0000 0000 0000 0000 1000
0x03d0 0000 0000 0000 0000 0000 0000 0000 0000
0x03e0

Воспроизведя баг, мне нужно было найти тот из 17 хопов, на котором возникало повреждение. Я не мог просто позвонить провайдерам всех кластеров и попросить проверить их системы.

Я решил последовательно пропинговать каждый роутер, вдруг это поможет. Написал специальные ICMP-пакеты, достаточно большие, чтобы превысить безопасный рубеж в 576 байтов, и заполнил их нулями. Затем с помощью этих пакетов пропинговал из Лондона монреальский сервер.

Пакеты вернулись неповреждёнными.

Я перепробовал все сочетания скорости, содержимого, размера безрезультатно. Я не находил повреждений в вернувшихся пинговых ICMP-пакетах.

В netcat-конвейерах я заменил TCP на UDP. Опять никаких повреждений.

Для воспроизведения повреждений нужен был TCP, а для TCP нужны две взаимодействующие конечные точки. Я тщетно пытался выяснить, у всех ли маршрутизаторов есть открытый TCP-порт, с которым я могу взаимодействовать напрямую.

Казалось, нельзя было выявить со стороны сбойный хоп. Или можно?

Mirror mirror on the wall


Чтобы определить, возникает ли повреждение, нужно было воспользоваться одним из сценариев:

  • Через TCP-узел, с которым идёт взаимодействие, проверить пакет в пункте назначения.
    • Не в пользовательском пространстве, куда пакет не будет доставлен в случае ошибки при проверке контрольной суммы, а проверить полученный пакет на повреждения с помощью root и tcpdump.
  • С помощью TCP-узла, который работает как echo-сервер и зеркалирует обратно полученные данные, проверить пакет на отправляющей ноде.

Неожиданно выяснилось, что нам доступна вторая точка замера. Доступна не напрямую, но всё же: при самом первом подходе к решению проблемы мы заметили, что SSH-клиенты виснут, когда общаются с SSH-серверами через повреждающий хоп. Это хороший пассивный сигнал, который можно использовать вместо активного echo-сигнала.

И в этом нам могут помочь многочисленные открытые SSH-серверы в интернете.

Нам не нужны актуальные аккаунты на этих серверах, нужно лишь запустить SSH-соединение, посмотреть, будет ли успешной фаза обмена шифрами (при разумном количестве повторных попыток, чтобы учесть случайность повреждения).

План был такой:

  • Использовать замечательный инструмент nmap в режиме random IP для составления списка географически распределённых открытых SSH-серверов.
  • Протестировать каждый сервер и выяснить:
    • Если он не отвечает, непредсказуем или использует файрвол игнорировать его.
    • Если успешно общается после N-попыток пометить хорошим.
    • Если общается с зависаниями в фазе telltale после N-попыток пометить плохим.
  • Запомнить трассировку для хороших и плохих.

Я думал так: в трассировках всех плохих серверов будут использоваться несколько одинаковых хопов. Мы сможем выделить подозрительные хопы и определить те из них, которые используются в трассировках хороших серверов. В надежде, что останется один или два.

Потратив час на классификацию серверов вручную, я прекратил исследовать данные. У меня было 16 плохих и 25 хороших серверов.

Сначала нужно было составить список хопов, которые встречаются во всех трассировках плохих серверов. Почистив список, я понял, что мне даже не нужно переходить к списку хороших, чтобы убрать ложноположительные хопы. У плохих был только один общий хоп.

Теме не менее, до него было два провайдера: Лондон N хопов upstream1 Y хопов upstream2.

Это был первый из Y хопов в upstream2, прямо на границе между upstream1 и upstream2. Он повреждал случайные TCP-пакеты, что приводило к многочисленным повторным отправкам и, в зависимости от особенностей обмена данными протокола, к зависаниям или снижению объёмов передачи.

Вместе с отделом эксплуатации лондонского ЦОДа мы отследили IP-адрес этого хопа. Я надеялся, что благодаря их прямой связи с upstream1 получится заставить внести исправления.

Через upstream1 я получил подтверждение, что на указанном мной хопе (первом в upstream2) был внутренний сбой управляющего модуля, который влиял на BGP и маршрутизацию между двумя внутренними сетями. Они перестроили маршрут в обход сбойного устройства и отключили его в ожидании замены.

Фильтр рок-музыки


Я помогал пользователю потокового аудиоприложения настроить работу по локальной сети. У пользователя проигрывалась только классическая музыка, но не роковая. Серьёзно. Классика передавалась без проблем, а при попытке потоковой передачи рок-музыки соединение пропадало через несколько минут.

Приложение получало фрагменты аудио, сжимало их с помощью кодека, сжимающего без потерь, а затем отправляло каждый чанк в отдельном UDP-пакете конечной точке. По мере возможности приложение старалось использовать IPv6, потому что это было надёжнее LAN-окружения, хотя при необходимости могло работать и через IPv4.

После бесконечного и нудного поиска причины проблемы, я наконец-то понял, в чём дело. Каким-то образом пользователь задал в сетевом интерфейсе MTU 1200 байтов. А IPv6 не будет автоматически фрагментировать пакеты на уровне IP при MTU ниже 1280 байтов, так что более крупные пакеты просто не смогут отправиться. Поточное приложение будет пытаться отправить аудиопакеты крупнее 1200 байтов, получать ошибку и разрывать соединение.

Почему такое происходило только с рок-музыкой? Всё просто. Кодеки со сжатием без потерь используют переменный битрейт, а классическая музыка сжимается лучше роковой. При поточной передаче классики звук стабильно сжимался в пакеты менее 1200 байтов, а пакеты с роковой музыкой случайным образом превышали этот порог.

Пользователь не знал, почему уменьшен его MTU, он ему и не был нужен, так что мы увеличили значение и всё стало прекрасно работать.

Самоисчезающий перебой в работе интернета


Поступив в 1999-м в университет, я жил в старом и ветхом студенческом общежитии, потому что не мог позволить себе ничего лучше. Но в общаге хотя бы был довольно приличный интернет, который в моей стране ещё не был широко распространён. А поскольку менять здание запрещалось, сетевые кабели (ещё коаксиальные) были разведены по временной схеме. Их прятали за подвесным потолком в коридорах и протягивали через дверные проёмы в комнаты, где они просто лежали на полу. Любой разрыв связи мог привести к тому, что без сети оставался целый этаж. Поскольку я учился на факультете информатики, то быстро и невольно превратился на своём этаже в человека, который исправляет довольно частые перебои, хотя у меня вообще не было опыта работы с сетями.

Иногда перебой был на стороне провайдера, иногда проблема была связана с нашим прокси, но чаще всего кто-то просто отключал какой-то кабель и не вставлял в него замыкатель.

Однажды вечером пропал интернет, но всего на несколько минут. Затем он снова появился, так что я не придал этому значения. Но на следующий день кратковременный перебой повторился, и на третий день тоже. Обычно он происходил около 20 часов, точное время плавало, а иногда его вообще не было. Но каждый раз, когда сеть пропадала, начинал звонить мой внутриобщажный телефон, а людей всё сильнее раздражали эти повторяющиеся перебои.

Поскольку каждый перебой длился всего несколько минут, я не мог определить конкретное место до того, как сеть снова появлялась. Пробовал пробежать по этажу и стучаться во все двери, спрашивая, не вытащил ли кто-то кабель или не сделал ли с ним что-то, но затея не помогла. Наконец я решил дожидаться ежедневного перебоя со своим верным мультиметром в руке. В течение недели я исключал из подозреваемых одну комнату за другой. Наконец в одном из комнатных кабелей я обнаружил всплеск сопротивления в ходе очередного перебоя.

Я постучал, но мне не открыли. Замок был заперт. Но если в комнате нет никого, кто мог бы что-то сделать с компьютером или кабелем, то почему прерывается соединение? И почему оно восстанавливается? На следующий день всё повторилось, мне снова не открыли на стук в дверь. Я решил совсем отключить эту комнату, чтобы у остального этажа работал интернет.

На следующее утро жильцы той комнаты сообщили мне, что у них не работает интернет. Я пришёл к ним и измерил сопротивление во всех кабелях, проверил все подключения и замыкатели. Во всех кабелях ноль Ом, всё в идеальном порядке. Я спросил парня, что он делал прошлым вечером? Читал учебники перед экзаменами, ничего связанного с компьютером, ответил тот. Я перепроверил всё второй и третий раз, но не нашёл никаких проблем. Я почти сдался, и тут заметил: кабель был закреплён под кроватью. Конечно, медный сердечник кабеля был сломан именно в этом месте, но удерживался оболочкой достаточно плотно, чтобы при нормальных условиях контакт сохранялся, даже если сесть на кровать. Но когда я начал раскачивать её, контакт пропадал на несколько секунд при каждом толчке.

Сами можете предположить, что происходило на той кровати по несколько минут каждый вечер, за запертой дверью и без ответа на стук.

История Мэла


Настоящие программисты пишут на Фортране


Возможно, сейчас это так, в декадентскую эпоху безалкогольного пива, калькуляторов и user-friendly приложений, но в Старые Добрые Времена, когда термин software звучал забавно, а Настоящие Компьютеры были сделаны из магнитных барабанов и радиоламп, Настоящие Программисты писали на машинном коде. Не на FORTRAN. Не на RATFOR. Даже не на ассемблере. На машинном коде. На настоящих, неприукрашенных, непостижимых шестнадцатеричных числах. Прямо так. Уже несколько поколений программистов выросло, не зная об этом славном прошлом, и я считаю, что должен постараться перекинуть мостик через разрыв поколений и рассказать о том, как Настоящий Программист писал код. Я буду звать его Мэл, потому что так его звали.

Я познакомился с Мэлом, когда устроился в Royal McBee Computer Corp., ныне несуществующую дочернюю компанию производителя печатных машинок. Фирма производила LGP-30 маленький и дешёвый (по сегодняшним меркам) компьютер на барабанной памяти, и только что начала производить RPC-4000, тоже на барабанной памяти, намного улучшенный, более крупный и быстрый. Магнитные сердечники стоили слишком дорого, да они и не выдержали конкуренции (поэтому вы не слышали ни об этой компании, ни о её компьютерах). Меня наняли, чтобы я написал FORFTRAN-компилятор для этого нового чуда, а Мэл был моим проводником по его возможностям. Мэл не одобрял компиляторы. Что хорошего в том, что программа не может переписать собственный код?, спрашивал он. Мэл написал на шестнадцатеричном коде самую популярную программу компании. Она работала на LGP-30 и играла в блэкджек с потенциальными покупателями на компьютерных выставках. Это всегда оказывало драматический эффект. Стенд с LGP-30 выставлялся на каждой выставке, а продавцы IBM собирались вокруг и беседовали друг с другом. Помогало ли это продавать компьютеры? Этот вопрос мы никогда не обсуждали.

В обязанности Мэла входило переписывание блэкджек-программы под RPC-4000. (Портирование? Что это такое?) У нового компьютера была схема адресации один-плюс-один: у каждой машинной инструкции кроме кода операции и адреса нужного операнда был ещё и второй адрес, который показывал, где на вращающемся магнитном барабане записана следующая инструкция. То есть после каждой инструкции шло GO TO! Набейте это в трубку Pascal и выкурите.

Мэл любил RPC-4000, потому что мог оптимизировать свой код: размещать инструкции на барабане так, чтобы как только одна завершалась, вторая сразу оказывалась под считывающей головкой и была готова к немедленному исполнению. Для этого была написана программа, оптимизирующий ассемблер, но Мэл отказывался ею пользоваться. Никогда не знаешь, куда она положит данные, объяснял он, поэтому приходится использовать отдельные константы. Я понял суть этой фразы гораздо позже. Поскольку Мэл знал числовые значения всех операционных кодов и присваивал в барабанной памяти собственные адреса, то каждую написанную им инструкцию можно было считать числовой константой. К примеру, он мог выбрать более раннюю инструкцию сложения и умножить на неё, если она имела подходящее числовое значение. Его код мало кто мог изменять. Я сравнивал вручную оптимизированные Мэлом программы с тем же кодом, который был обработан оптимизирующим ассемблером, и код Мэла всегда исполнялся быстрее. Дело в том, что метод построения архитектуры сверху вниз ещё не изобрели, да Мэл всё равно не пользовался бы им. Сначала он писал внутренние части своих программных циклов, чтобы те первыми получали оптимальные адреса на барабане. А оптимизирующий ассемблер был на такое неспособен. Мэл никогда не писал циклы с задержкой по времени, даже когда неповоротливый Flexowriter требовал делать задержку между выводами символов. Мэл просто размещал инструкции на барабане так, чтобы в момент, когда нужно было считать следующую инструкцию, она проходила мимо считывающей головки, и барабану требовалось сделать ещё один оборот, чтобы её найти. Мэл нашёл для этой процедуры неподражаемый термин. Слово оптимальный (optimum) имеет абсолютное значение, как и уникальный, поэтому в разговорной речи их стали часто делать относительными: не совсем оптимально, или менее оптимально, или не очень оптимально. Мэл называл места на барабане с наибольшим временем задержки самый пессимум (pessimum наихудшие условия среды, переносимые организмом).

Завершив работу над блэкджек-программой и запустив её (Даже инициализатор оптимизирован, гордо сказал он), Мэл получил от отдела продаж заявку на внесение изменений. За перемешивание карт и сдачи из колоды в программе отвечал элегантный (оптимизированный) генератор случайных чисел. И кто-то из продажников посчитал это слишком честным, потому что иногда покупатели проигрывали. Они попросили Мэла изменить программу так, чтобы с помощью сенсорного включателя на консоли можно было изменить шансы игрока и позволить покупателю выиграть. Мэл отказался. Он считал это нечестным так оно и было, и что это посягает на его нравственность программиста так оно и было, поэтому отказался в этом участвовать. Мэла уговаривал начальник отдела продаж, и Большой Босс, и коллеги-программисты по настоянию Босса. Наконец Мэл сдался и написал код, но сделал жульническую проверку наоборот: когда включатель был включён, программа жульничала и всегда выигрывала. Мэл был в восторге от своего решения. Он утверждал, что его подсознание проявило неуправляемую этичность и наотрез отказался исправлять программу. Когда Мэл ушёл из компании ради более высокого заработка, Большой Босс попросил меня взглянуть на код и сказать, смогу ли я найти модуль проверки и поменять порядок его работы. Я неохотно согласился.

Разбирательство с кодом Мэла было настоящим приключением. Мне часто казалось, что программирование это вид искусства, настоящую ценность которого может оценить лишь тот, кто разбирается в этом загадочном искусстве. В нём встречаются настоящие драгоценности и блестящие ходы, самой природой процесса скрытые от человеческого взгляда и восхищения, иногда навсегда. Можно многое узнать о человеке, просто читая его код, даже шестнадцатеричный. Думаю, Мэл был непризнанным гением. Пожалуй, самым сильным потрясением стал найденный мной невинный цикл, в котором не было жульнической проверки. Нет проверки. Нет.

Здравый смысл подсказывал, что это должен быть закрытый цикл, внутри которого циркулирует программа, вечно, бесконечно. Однако программное управление успешно проходило через него и безопасно выходило на другой стороне. У меня ушло две недели, чтобы разобраться в этом. Компьютер RPC-4000 был оснащён современным устройством индексным регистром. Он позволял писать программные циклы, внутри которых использовались индексированные инструкции. При каждом проходе через цикл число из регистра добавлялось к адресу инструкции, чтобы она ссылалась на следующую позицию в серии. Оставалось только инкрементировать индексный регистр при каждом проходе. Мэл этим не воспользовался. Вместо этого он вытягивал инструкцию в машинный регистр, добавлял к её адресу единицу и сохранял обратно. А затем исполнял модифицированную инструкцию прямо из регистра. Цикл был написан с учётом дополнительного времени на исполнение: как только инструкция завершалась, следующая оказывалась под считывающей головкой барабана. Но в цикле не было жульнической проверки. Спасительной подсказкой оказалось то, что был включён бит в индексном регистре он располагался в коде команды между адресом и операционным кодом. Однако Мэл не использовал индексный регистр, оставляя его обнулённым.

Когда наступило прозрение, я едва не ослеп. Данные, с которыми он работал недалеко от верхних уровней памяти крупнейшие адреса, на которые могли ссылаться инструкции, Мэл разместил так, чтобы после обработки последней позиции инкрементирование адреса инструкции приводило к переполнению. При переносе к операционному коду прибавлялась единица, меняя его на следующий код в наборе: инструкцию перехода. Конечно же, эта следующая инструкция располагалась по нулевому адресу, и программа радостно туда отправлялась. Я не общался с Мэлом и не знаю, сдался ли он перед потоком перемен, который затопил с тех пор программирование. Предпочитаю думать, что не сдался. Я был настолько впечатлён, что перестал искать жульническую проверку и сказал Большому Боссу, что не могу её найти. Он не удивился. Когда я ушёл из компании, блэкджек-программа всё ещё жульничала, если включали нужный включатель, и это правильно, как мне кажется. Мне не нравилось хакать код Настоящего Программиста.

Исключительно проблема USB


Прямо из колледжа я устроился в компанию и в течение пяти месяцев работал над потребительским устройством, прежде чем его показали публике. Устройство работало под управлением Linux. И пока я свыкался с идеей баловства в пространстве ядра, меня выдернули на встречу по расстановке приоритетов в устранении багов. Многочисленных багов. Сотен багов. На каждом из которых написано: это невозможно, как такое произошло?.

Они кричали: Повреждение памяти!. Я думал: Хоспади, исправляйте свои баги. Просматривая дампы падений, мы увидели что это? Программа выполнила запрещённую инструкцию, объединяя две строки с помощью функции из стандартной библиотеки. Хм, странно Следующий журнал: нельзя извлечь страницу из файла подкачки на устройстве, на котором вообще не выделено место для файла подкачки (кажется, я понимаю, почему мы не могли извлечь страницу!).

Когда-то я написал короткую программу. Она выделяла 80 % системной памяти под один массив и записывала в него последовательные целые числа. Затем ждала, чтобы нажали Enter, и проверяла, не изменилось ли содержимое массива. Теперь я загрузил эту программу, подождал 30 секунд, а затем запустил проверку. Никаких проблем. Попытался ещё несколько раз ха, я знал, что никакого повреждения памяти нет! Я выдернул отладочный кабель (USB), секунд через 10 несколько раз быстро вставил и выдернул, затем снова вставил. Бам! 90 ошибок.

Твою же.

Ладно, придётся повозиться с USB-портом. Получается, проблема связана с ним? Не похоже, что драйвер USB реализует волшебный bit fairy-алгоритм, который случайным образом разбрасывает битовые ошибки. Наверное, проблема с железом? Нет, не с ним, но это не помешало нам творить всякие непотребства с USB-портом. Позвали инженеров, которые давно переключились на другой продукт, и теперь они ломали голову над проблемой. Я не помню, сколько времени мы потратили, доказывая себе, что с аппаратной частью был полный, полный, пооооолный порядок. Заземление было в порядке, напряжение стабильное, часы шли точно, а схема DDR-линий была настолько идеальной, что вы заплакали бы от счастья, увидев её.

Устройства, которые тестировались инженерами, становились всё более нестабильными. Я предположил, что аппарат может загрузить данные в память, получить битовые ошибки, а затем выгрузить обратно во флеш-память, возможно даже не в то место (таблица страниц часто повреждалась, так что можно было допустить, что это происходит и со структурами отслеживания файлов. Содержимое могло записываться в неправильные места, а структуры файловой системы могли ломаться, и т.д.) Со временем устройства деградировали настолько, что уже не могли надёжно загрузиться. Наконец один из инженеров сломался и перезаписал в память образ, который лежал у него на ноутбуке. Этот образ был относительно древним.

Чувак. Дело в программном обеспечении.

Что?!?!?! Уверяю, мы не писали bit fairy!

Нет: он залил сборку трёхмесячной давности, и проблема исчезла. В этот момент я чувствовал себя ответственным за то, что вовлёк кучу людей в очень долгую и бессмысленную затею, поэтому остался на ночь и провёл бинарный поиск по всем патчам за прошедшие месяцы (на изучение полных сборок целой ОС ушло больше времени, чем мне хотелось бы).

Так что это был за волшебный патч? Кто-то добавил в ядро драйвер для чипа, который мы анализировали. Этого чипа в устройстве не было.

Ха! Мы нашли ведьму! СЖЕЧЬ ЕЁ!

Многие объявили, что задача решена. Они были счастливы, что в ближайшем релизе можно откатить патч и жить дальше. Мы откатили его с крайней придирчивостью, собрали образ, протестировали, всё было хорошо. Мы не предполагали, что через несколько дней тот же дефект появится в ядре.

Погодите. Если чипа не было на плате, как нам помешал драйвер? Я запускал lsmod, драйвер не был загружен Да и ладно, какая разница, удалю файл модуля и перезагружу. Нифига, проблема осталась. Это ненормально...

Теперь я был один и наблюдал за происходившей чертовщиной. Начал внимательно анализировать патч. Это был милый файл в 10 тыс. строк на С, который нам предоставил производитель чипа. Описывать его словом хаос было бы слишком снисходительно (справедливости ради, через несколько недель они прислали нам гораздо более продуманный драйвер). Поковырявшись немного, я решил, что в драйвере не было реализовано битовое-жонглирование-ради-забавы. Так в чём же дело? 48 байтов из пяти строк кода. Маленькая структура в загрузочном файле, в которой говорится, по какому адресу шины нужно искать чип. Я удалил большую часть драйвера, но оставил в нём другую структуру. Проблема не исчезла.

Итак, мальчики и девочки, у нас проблема с выравниванием! Каким-то образом эта 48-байтная структура что-то двигает в памяти, и это приводит к ошибкам. Я выяснил, что проблема возникает, когда помещаешь в файл что-нибудь больше 32 и меньше 64 байтов. Это знание не слишком помогло, но хотя бы создавало ощущение прогресса.

Сборка ядра выдавала аккуратный файл System.map. В нём перечислялось, где в виртуальном адресном пространстве ядра находятся все переменные, скомпилированные в ядре. Я выяснил, что моя маленькая структура находится посреди раздела .data. Этот раздел заполнен инициализированными переменными, так что когда бинарник ядра распаковывался в памяти, он записывал все эти переменные из скомпилированного образа. Пользуясь System.map как справочником, я реализовал довольно бестолковый бинарный поиск. По большей части я искал по линкерам разных С-файлов. Я нашёл переменную, с которой нужно было сравнивать; нашёл файл ядра, который её содержит; положил рядом в случайном файле мою волшебную структуру и начал смотреть, проявится ли снова проблема.

Процедура поиска дошла до последних нескольких элементов .data и вернулась с пустыми руками. В памяти с инициализированными переменными не было нужных данных. Полистав дальше файл System.map, я увидел, что не обратил внимания на целый раздел .bss, в который попадали неинициализированные переменные. Наученный прежними ошибками, я сначала проверил начало и конец. Конечно, неинициализированная переменная в начале раздела приводила к ошибкам, а переменная в конце раздела не приводила. Поиск виновника был лишь делом времени. Переменной, чьё перемещение приводило к проблеме, был

Указатель функции?!

Как, чёрт побери, выравнивание указателя функции рушит нашу систему? В архитектуре ARM нельзя читать слова при обращении без выравнивания, то есть каждую 32-битную переменную нужно класть в память по адресу, кратному 4. Указатель функции не исключение, он всегда получает минимальный адрес. Оказывается, в нашей проблемной ситуации адрес был кратен 2n, большей либо равной 64. Любое значение меньше этого порога и проблема пропадала. С выравниванием указателя тоже был порядок.

Не бывает слишком хорошего выравнивания. По крайней мере, не было до возникновения этого бага.

Теперь этот указатель функции не был дедовским указателем. Он ссылался на что-то особенное. В SRAM процессора была область, которую мы могли использовать для связанных с загрузкой задач, если не могли использовать RAM. Чтобы экономить энергию во время простоя, мы скопировали в эту область подпрограмму, задали особый указатель, который ссылался на неё, а потом его вызывали. Что делала подпрограмма? Давайте взглянем на ассемблер. Я не специалист по ARM-ассемблеру, но комментарии были достаточно красноречивы.

// Вычисляет адрес привязанного к памяти управляющего регистра... ... // Теперь выключаем контроллер памяти и переводим LPDDR в режим самоообновления

ЧТО вы делаете?! Быстро же вы перешли от базовых операций с регистрами к отключению контроллера памяти. Я отправил письмо производителю, который написал подпрограмму, и спросил, не упустили ли они что-то.

Через три дня мне пришёл ответ в стиле Ах да, там должен быть барьер памяти. Получается, что из-за структуры их L2-кэша им пришлось бы дополнительно поддерживать TLB, если бы мы случайно записали в адрес памяти, кратный 64. В таких случаях мы всё ещё можем использовать оперативную память при выключенном контроллере.

Учитывая, что для выравнивания переменных нужна минимальная кратность 4, и что для последней записи не может быть кратности 64 или больше, при каждом компилировании одна шестнадцатая часть данных оказывалась совершенно непригодной для использования системой.

В конце концов мы отгрузили надёжный продукт с барьером памяти, и покупателям он понравился. Да, и если вам интересно, я не мог этого заметить с помощью USB-кабеля, потому что мы не могли войти в режим низкого энергопотребления из-за использования USB. Это исключительно проблема USB.

Неверное сообщение об ошибке


В последние часы 17 сентября 1996, за день до запланированного запуска сервиса WebTV, наша группа собралась в эксплуатационном центре в Пало-Альто. Поблизости болталась толпа сисадминов-сетевиков и разработчиков сервисного ПО, чтобы стать свидетелями официального запуска.

Когда пробил назначенный час, один из сетевиков начал регистрироваться на своём устройстве WebTV. Мы понимали, что хорошие ники быстро закончатся, поэтому важно было зарегистрироваться до того, как это начнут делать пользователи. К тому же было приятно оказаться в числе первых, кто зарегистрируется на первом настоящем сервисе. До этого все аккаунты были одноразовыми тестовыми.

Несколько человек столпились вокруг, глядя, как он набирает на клавиатуре, ощущая головокружение от предвкушения и недосыпа. Брайс ввёл своё имя, адрес и другую информацию, а затем начал печатать ник. Это было его имя для адреса электронной почты. Он набрал jazz, то есть его почта должна была быть jazz@webtv.net. Когда он нажал Enter на беспроводной клавиатуре, мы услышали характерный звук, обозначающий появление сообщения об ошибке. Все посмотрели на экран.

Чтобы понять произошедшее далее, важно кое-что знать о работе сервиса. WebTV позиционировался как семейный, поэтому нужно было проверять на сквернословие и отфильтровывать пользовательские имена и прочую видимую для пользователей информацию. Всё выловить невозможно, но очевидные вещи отфильтровать несложно.

Пользовательские имена сравнивались со списком регулярных выражений, которые позволяли сравнивать с шаблоном. Например, fu.*bar будет сравнивать со всеми именами, начинающимися с fu и заканчивающимися на bar. Если тщательно подобрать паттерны, можно выловить и отклонить такие вопиющие варианты, как shitake и matsushita, в которые встроены ругательства.

Тот же механизм использовался для того, чтобы пользователи не могли выбирать запрещённые имена вроде postmaster, root, admin и help. У нас был такой текстовый файл:

admin.*Имя пользователя не может начинаться с "admin".postmasterВы не postmaster.poopЭто плохое слово.weenieЭто плохое слово.

Каждая запись состояла из двух строк. Первая была регулярным выражением, с которым проводилось сравнение, а вторая строка была сообщением об ошибке, которое показывалось пользователю. Система читала файл сразу по две строки, и когда пользователь вводил имя, оно сравнивалось со всеми регулярными выражениями. Для первого найденного совпадения выводилось сообщение об ошибке. Если совпадений не было, пользовательское имя принималось.

Код, читавший файл, умел пропускать комментарии. Но он не умел обрабатывать пустые строки.

Кто-то внёс изменения в файл с ругательствами, попутно добавив одну пустую строку после зарезервированных имён и перед ругательствами. Когда код читал список, он принимал пустую строку за регулярное выражение, а следующее за ней слово за сообщение об ошибке. А выражение в виде пустой строки совпадает с чем угодно.

Полночь. Мы все немного на взводе. Брайс пишет имя, а система отвечает простым сообщением:


Мы начали истерически ржать. К нам подошли другие, чтобы узнать, что происходит. Мы показали на экран. Они начали истерически ржать.

В это время в другом здании Марк Армстронг (отвечавший за QA) вместе с Брюсом Ликом (одним из основателей компании) сидели перед стойкой из шестнадцати приставок WebTV. Эта стойка, прозванная racksville, была подключена через видеомультиплексор к большому телевизору, одновременно показывающему изображения со всех 16 приставок. Марк и Брюс начали регистрировать приставки, пользуясь клавиатурой с инфракрасным передатчиком. Мы позвонили им по интеркому:

Как у вас идёт?

Всё отлично.

А, хорошо. Вы могли кое-что заметить при регистрации.

Да? Мы не заметили ничего странного.

Заметите.

Ладно. Вводим почтовый индекс пока всё нормально. ОГО!!!

На изображениях со всех 16 приставок возникло дружелюбное сообщение. Начальники предположили, что нам, быть может, стоит поскорее исправить этот глюк. Это показалось нам отличной идеей.

Мы исправили файл, и научили код распознавать и игнорировать пустые строки. Насколько я знаю, WebTV не сказал ни одному клиенту f--k.

Проблема с падением Xbox


В то время команда работала над одной из первых игр для совершенно новой приставки под названием Xbox. Когда финальное тестирование ускорили, QA запустили три приставки из установочной партии, чтобы гонять ночью автоматизированные тесты. Если вчерашняя сборка игры утром всё ещё тестировалась, это говорило о её стабильности.

К сожалению, утром одна из консолей упала. Падения это всегда плохо, но это был на редкость плохой случай: что-то, исполнявшееся видеокартой, обрушило всю систему. Диагностировать проблемы с видеокартой тяжело: никаких отладчиков, никакой трассировки стека, никакой отладки с помощью printf. Можно только читать код и экспериментировать.

Так началась Охота на Баг. Каждый день ведущие инженеры просматривали имеющиеся улики, выдвигали гипотезы и исключали возможности. Каждую ночь QA получали случайное падение без какой-либо причины. Это невозможно, Как это происходит?, Может, это баг в компиляторе? все самые популярные хиты.

На машине инженеров игра работала идеально, по много дней. Но это было слабым утешением, потому что близился дедлайн отправки игры в печать и отгрузки в магазины.

К счастью, скоро удалось найти закономерность, хотя и довольно странную. Игра падала только ночью и только на одной из трёх приставок. Начали искать различия между ними. Дело было не в кабеле питания. Не в контроллерах. Не в порядке записи DVD. Переносили приставку на свой стол не падает. Ставили обратно падает. Дело было в специфическом стенде, который использовали QA.

Теперь процесс исключения факторов требовал исключить все переменные. В конце концов, отчаявшись, инженер попытался поменять приставки на столе местами.

Оказалось, сбойной была не конкретная приставка. Падала любая приставка, стоявшая на этом столе. Посреди ночи. Иногда ради науки приходится поступать странно, и это был один из таких случаев. Инженер стоически уселся в кресло, обложился банками с Red Bull, и Охота на Баг превратилась в Наблюдение за Багом. Инженер поклялся, что будет смотреть, как на стоящих на этом проклятом столе приставках выполняются автоматизированные тесты, пока не увидит сбой собственными глазами.

Ночь тянулась медленно, затем быстро, и наконец наступил рассвет. Игра продолжала работать. Это вдохновляло. Стало подниматься солнце.

И тут наконец-то произошло кое-что интересное: на стол упал луч восходящего солнца. Минута за минутой луч полз по столу к приставкам, его тёплое сияние тихо обволакивало чёрный купол приставки.

Которая быстро упала.

У первых Xbox оказалась проблема: видеокарта могла сбоить, если температура приставки достигала определённого значения. Программное обеспечение было ни при чём. Об аппаратной проблеме сообщили, игру выпустили, а Red Bull заменили на пиво. Ну ладно, будем честны, на виски. Один: ноль в пользу науки.
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru