Какая охота на жуков была для вас самой сложной и как вам удалось их найти и уничтожить?

softwareengineering.stackexchange https://softwareengineering.stackexchange.com/questions/2699

  •  16-10-2019
  •  | 
  •  

Вопрос

Это вопрос типа "Поделитесь знаниями".Мне интересно учиться на ваших успехах и /или неудачах.

Информация, которая может оказаться полезной...

Предыстория:

  • Контекст:Язык, приложение, Окружающая среда и т.д.
  • Как была выявлена ошибка ?
  • Кто или что выявило ошибку ?
  • Насколько сложным было воспроизведение ошибки ?

Охота.

  • Каков был ваш план ?
  • С какими трудностями вы столкнулись ?
  • Как в конце концов был найден код - нарушитель ?

Убийство.

  • Насколько сложным было исправление ?
  • Как вы определили объем исправления ?
  • Какой объем кода был задействован в исправлении ?

Посмертно.

  • Какова была техническая первопричина ? переполнение буфера и т.д.
  • Какова была первопричина падения с высоты 30 000 футов ?
  • Сколько времени в конечном счете занял этот процесс ?
  • Были ли какие - либо функции , на которые негативно повлияло исправление ?
  • Какие методы, инструменты, мотивации вы сочли особенно полезными?..ужасно бесполезный ?
  • Если бы ты мог сделать все это снова ?............

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

Это было полезно?

Решение

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

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

Мы попробовали обычные шаги:

(1) попросили их переключать компьютеры с другим пользователем, у которого никогда не было проблемы, чтобы исключить компьютер/конфигурацию. - Проблема следовала за ними.

(2) заставили их войти в приложение и работать как пользователь, который никогда не видел проблему. - Проблема все еще следовала за ними.

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

(4) попросил разработчика сидеть с пользователями и смотреть их весь день. Они видели ошибки, но не заметили, что они делают что -то необычное, чтобы вызвать их.

Мы боролись с этим в течение нескольких недель, пытаясь выяснить, что общего у «пользователей ошибок» не было, что у других пользователей этого не сделали. Я понятия не имею, как, но у разработчика в шаге (4) был момент Eureka на работу, чтобы работать однажды, достойная энциклопедии Брауна.

Он понял, что все «пользователи ошибок» были оставлены, и подтвердил этот факт. Только левша пользователи получили ошибки, никогда не верны. Но как быть левшом вызвать ошибку?

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

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

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

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

Это было отныне известно в Legend в команде Dev как "Левая ошибка"

Другие советы

Это из длинная Давным назад (конец 1980 -х).

Компания, в которой я работал, написала пакет CAD (в Fortran), которая работала на различных рабочих станциях UNIX (HP, Sun, Silcon Graphics и т. Д.). Мы использовали наш собственный формат файла для хранения данных, и когда пакет был запущен на дисковом пространстве, так что было много смены битов, используемого для хранения нескольких флагов в заголовках объектов.

Тип объекта (линия, дуга, текст и т. Д.) Был умножен на 4096 (я думаю) при хранении. Кроме того, это значение было отрицательным для указания удаленного элемента. Итак, чтобы получить тот тип, который у нас был код, который сделал:

type = record[1] MOD 4096

На каждой машине, кроме одной, это давало ± 1 (для линии), ± 2 (для дуги) и т. Д., И мы могли бы затем проверить знак, чтобы увидеть, был ли удален.

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

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

В конце концов я обнаружил, что это потому, что в то время как каждый другой производитель внедрил MOD чтобы -4096 MOD 4096 в результате -1 HP реализовал его математически правильно, чтобы -4096 MOD 4096 в результате -4097.

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

Это заняло несколько дней.

Вау, хорошее чтение здесь!

Моей самым сложным было много лет назад, когда Turbo Pascal был большим, хотя это могло быть одним из ранних C ++ IDE того времени. Как единственный разработчик (и третий парень в этом стартапе), я написал что-то вроде упрощенной программы CAD, удобной для продавцов. В то время это было здорово, но разработал неприятный случайный аварий. Это было невозможно воспроизвести, но случалось достаточно часто, чтобы я отправился на охоту за жуками.

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

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

Оказалось, что он набил 16-битный int в стеке, но подпрограмма ожидает 32-битную. Или что-то вроде того. Компилятор не автоматически накладывал все значение до 32 -битных и проходило достаточную проверку типа. Это было тривиально исправить, лишь часть одной линии, вряд ли какая -либо мысль требуется. Но чтобы добраться туда заняла три дня охоты и подвергнуть сомнению очевидное.

Таким образом, у меня есть личный опыт работы с этим анекдотом о том, что приходит дорогой консультант, через некоторое время загадает куда -нибудь и взимает 2000 долларов. Руководители требуют разбивки, и это 1 доллар за TAP, 1999 долл. США за знание, куда использовать. За исключением того, что в моем случае это было время, а не деньги.

Извлеченные уроки: 1) Используйте лучшие компиляторы, где «Лучшие» определяются как включение проверки столько проблем, сколько компьютерные науки знают, как проверить, и 2) поставить под сомнение простые очевидные вещи или, по крайней мере, подтвердите их надлежащее функционирование.

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

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

Состояние гонки с сетевыми данными из ада

Я писал сетевой клиент/сервер (Windows XP/C#), чтобы работать с аналогичным приложением на действительно старой (Encore 32/77), написанной другим разработчиком.

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

Это сделало это с 3 слоистой структурой. Процесс коммуникаций прочитал/написал данные на/от хоста, выполнял все необходимые преобразования формата (эндезианство, формат с плавающей запятой и т. Д.) И написал/прочитал значения в/из базы данных. База данных действовала в качестве посредника данных между коммуникационными и сенсорными интерфейсами. Приложение с сенсорным экраном сгенерировало интерфейсы сенсорного экрана на основе того, сколько мониторов было прикреплено к ПК (оно автоматически обнаружило это).

В временной рамке, полученной пакетом значений между хостом и нашим компьютером, может отправлять только 128 значений максимума по проводам за раз с максимальной задержкой ~ 110 мс за переход к кругу (UDP использовался с прямым соединением x-over Ethernet между Компьютеры). Таким образом, количество переменных, разрешенных на основе переменного числа прикрепленных сенсорных экранов, было под строгим контролем. Кроме того, у хоста (хотя у него довольно сложная многопроцессорная архитектура с общей шиной памяти, используемой для вычислений в реальном времени) имел около 1/100-го мощности обработки моего мобильного телефона, поэтому ему было поручено сделать как можно меньше обработки, и его сервер /Клиент должен был быть написан в Ассамблее, чтобы обеспечить это (хост выполнял полную симуляцию в реальном времени, которая не может повлиять на нашу программу).

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


Чтобы определить проблему, я выбрал одно из колебательных значений:

  • Я проверил приложение с сенсорным экраном, оно колебалось
  • Я проверил базу данных, колеблюсь
  • Я проверил приложение Comms, колеблюсь

Затем я разразился Wireshark и начал вручную декодировать захваты пакетов. Результат:

  • Не колеблющиеся, но пакеты выглядели не правильно, было слишком много данных.

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

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

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

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

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


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


Уроки выучены:

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

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

Общее время, чтобы починить, составило 2-3 дня, когда большую часть этого времени потратил на работу над другими вещами, когда я был разочарован этим.

SIDENOTE: рассматриваемый компьютер хост не поддержал Ethernet по умолчанию. Карта для управления ее была сделана на заказ и модифицированной, а стек протоколов практически не существовал. Разработчик, с которым я работал, был одним адским программистом, он не только внедрил урезанную версию UDP и мимимальный фальшивый стек Ethernet (процессор не был достаточно мощным, чтобы справиться с полным стеком Ethernet) в системе для этого проекта Но он сделал это менее чем за неделю. Он также был одним из первоначальных лидеров команды проекта, которые в первую очередь спроектировали и запрограммировали ОС. Скажем так, все, что ему когда -либо приходилось делиться в компьютерах/программировании/архитектуре, независимо от того, как долго или сколько я уже новый, я бы послушал каждое слово. Нет ничего более ценного, чем работать с хорошими людьми, которые имеют искреннюю страсть к тому, что они делают.

Фон

  • В миссии критической приложения WCF, управляемой веб -сайтом и предоставлением бэкэнд -тразакционной обработки.
  • Приложение большого объема (сотни вызовов в секунду)
  • Несколько серверов несколько экземпляров
  • Сотни прошедших модульных испытаний и бесчисленные атаки QA

Баг

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

Как я это нашел

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

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

Затем я посмотрел на Тесс Феррандес Блог создал файл дампы пользователя и аннолировал его WindeBug в следующий раз, когда сервер примет дамп. Обнаружил, что все мои потоки были застряли int dictionary.add функция.

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

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

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

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

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

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

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

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

Написано в C ++, мы использовали Поко Для этого, так как это позволяет хорошо программировать IO, розетку и нить.


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

Случайно, компьютер делился своим IP Localhost вместо его удаленного IP.

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

Как мы это определили? Когда мы улучшили вывод в The Serserver, который мы обнаружили в более поздний момент, когда мы перезагрузили компьютеры, которые наш сценарий определил IP, был неправильным. Случайно, устройство LO было перечислено первым вместо устройства ETH0 ... действительно глупо. Итак, теперь мы жестко закодировали его из ETH0, так как это разделяется среди всех университетских компьютеров ...


А теперь более раздражающий:

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

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

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

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


Уроки выучены:

  • Не делайте глупые предположения, как порядок сетевых устройств.

  • Фреймворки не всегда выполняют свою работу (либо реализация, либо документация) правильно.

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

  • Когда код не был проверен на единицу (потому что это слишком сложно), не думайте, что все работает.

Я все еще нахожусь в своей самой сложной охоте на ошибку. Это один из тех, кто иногда там, а иногда и не ошибки. Вот почему я здесь, в 6:10 на следующий день.

Фон:

  • Контекст: язык, приложение, среда и т. Д.
    • PHP OS Commerce
  • Как была определена ошибка?
    • Случайный порядок, который работает частью случайного провала и перенаправить проблемы
  • Кто или что определило ошибку?
    • Клиент и проблема перенаправления была очевидна
  • Насколько сложно воспроизводила ошибку?
    • Я не смог воспроизвести, но клиент смог.

Охота.

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

Убийство.

  • Насколько сложным было исправление?
    • очень
  • Как вы определили объем исправления?
    • Там не было никаких областей ... это было везде
  • Сколько кода было вовлечено в исправление?
    • Все это? Я не думаю, что был файл нетронутым

Посмертный.

  • Какова была основная причина технически? переполнение буфера и т. Д.
    • Плохая практика кодирования
  • Какова была основная причина от 30 000 футов?
    • Я бы предпочел не сказать ...
  • Сколько времени в конечном итоге занял процесс?
    • Вечность и один день
  • Были ли какие -либо функции, негативно осуществленные исправлением?
    • особенность? или это ошибка?
  • Какие методы, инструменты, мотивы вы нашли особенно полезными? ... ужасно бесполезно?
  • Если бы вы могли сделать все это снова? ............
    • ctrl+del

Мне пришлось исправить некоторые запутанные вещи параллелизма в последний раз, но ошибка, которая все еще выделяется для меня, была в текстовой игре, которую я писал в Ассамблее PDP-11 для домашнего задания. Он был основан на игре в Конвея в жизни, и по какой -то странной причине большая часть информации рядом с сеткой постоянно перезаписывалась информацией, которой не должно было быть там. Логика была также довольно простой, так что это было очень запутанно. После того, как он перешел через это, чтобы заново открыть, что вся логика верна, я внезапно заметил, в чем проблема. Эта вещь: .

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

Это все еще выделяется для меня, потому что количество ущерба, нанесенное таким крошечным 4 пиксельным добавлением размером с 4 пикселя. Так в чем же вывод? Не кодируйте в сборке PDP-11.

Программа основной рамы перестала работать без причины

Я только что опубликовал это на другой вопрос.Смотрите сообщение здесь

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

Обновление 06/11/13: (исходный ответ был удален OP)

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

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

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

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

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

Затем я решил посетить операционный магазин и спросить их, установили ли они недавно какие-либо новые компоненты в основной рамке. Они сказали «да», мы недавно обновили компилятора. Хмммм.

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

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

Предыстория:

  • Контекст:Веб-сервер (C ++), который позволяет клиентам самостоятельно регистрироваться
  • Ошибка:При запросе страницы она просто не ответила бы, то есть вся ферма, и процессы были бы остановлены (и перезапущены), потому что им потребовалось слишком много времени (разрешено всего несколько секунд) для обслуживания страницы
  • Некоторые пользователи действительно жаловались, но это было крайне спорадично, поэтому в основном оставалось незамеченным (люди просто нажимают "Обновить", когда страница не отображается).Однако мы заметили дампы ядра ;)
  • Нам на самом деле так и не удалось воспроизвести в наших локальных средах, ошибка появлялась несколько раз в тестовых системах, но никогда не обнаруживалась во время тестов производительности ??

Охота.

  • План:Что ж, поскольку у нас были дампы памяти и журналы, мы хотели проанализировать их.Поскольку это влияло на всю ферму, и в прошлом у нас были некоторые проблемы с базами данных, мы подозревали, что база данных (одна база данных для нескольких серверов)
  • Трудности:Полный дамп сервера огромен, и поэтому они очищаются довольно часто (чтобы не заканчивалось место), поэтому нам пришлось быстро захватить один из них, когда это произошло...Мы упорствовали.Дампы показывали различные стеки (никогда никаких материалов DB, вот и все), сбой при подготовке самой страницы (не в предыдущих вычислениях) и подтвердил то, что показали журналы, подготовка страницы иногда занимала много времени, хотя это всего лишь базовый шаблонизатор с предварительно вычисленными данными (традиционный MVC)
  • Добираясь до этого:После еще нескольких проб и некоторого размышления мы поняли, что время было потрачено на чтение данных с жесткого диска (шаблона страницы).Поскольку это касалось всей фермы, мы сначала искали запланированные задания (crontab, пакеты), но тайминги никогда не совпадали от одного события к другому...Наконец до меня дошло, что это всегда происходило через несколько дней до того, как активация новой версии программного обеспечения, и у меня появился АхАх! мгновение...это было вызвано распространением программного обеспечения!Доставка нескольких сотен мегабайт (сжатых) может немного повлиять на производительность диска :/ Конечно, распространение автоматизировано, и архив отправляется на все серверы одновременно (многоадресная рассылка).

Убийство.

  • Исправьте Сложность:переключение на скомпилированные шаблоны
  • Затронутый код:нет, простое изменение в процессе сборки

Посмертно.

  • Первопричина:оперативная проблема или отсутствие перспективного планирования :)
  • Временная шкала:на поиск ушли месяцы, на исправление и тестирование - считанные дни, на контроль качества, тестирование производительности и развертывание - несколько недель. Спешить было некуда, поскольку мы знали, что развертывание исправления вызовет ошибку...и больше ничего...какой-то извращенец на самом деле!
  • Неблагоприятные побочные эффекты:невозможность переключения шаблонов во время выполнения теперь, когда они включены в поставляемый код, мы не часто использовали эту функцию, поскольку обычно переключение шаблонов означает, что у вас есть больше данных для ввода.Использования css в основном достаточно для "небольших" изменений макета.
  • Методы, инструменты: gdb + мониторинг!Просто нам потребовалось время, чтобы заподозрить наличие диска, а затем определить причину всплесков активности на графике мониторинга...
  • В следующий раз:относитесь ко всем вводам-выводам как к неблагоприятным!

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

Самый безумный, который я убил:

Чертежи печатают тамбурку!

Я смотрю на код и ничего не вижу. Я вытаскиваю работу из очереди принтера и проверяю ее, это выглядит нормально. (Это было в эпоху DOS, PCL5 со встроенным HPGL/2-на самом деле, очень хорошо для построения рисунков и без головных болей в создании растрового изображения в ограниченной памяти.) Я направляю его на другой принтер, который должен его понять, он печатает нормально Анкет

Отказавшись обратно код, проблема все еще существует.

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

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

Борланд Паскаль, код DPMI, чтобы справиться с некоторыми неподдерживаемыми API. Запустите его, иногда это сработало, обычно он стал бум, пытаясь справиться с неверным указателем. Это никогда не дало неправильного результата, хотя, как и ожидаете от топания указателя.

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

Виновник: их было два.

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

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

Это просто очень простая ошибка, которую я как -то превратил в кошмар для меня.

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

Ошибка: вместо двух переключателей потока в USERMODE, вместо этого это будет общей ошибкой защиты.

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

Проблема: где -то в начале охоты на ошибки я положил hlt Инструкция в CRT0. CRT0 - это в основном то, что загружает пользовательскую программу для использования в операционной системе. Этот hlt Инструкция вызывает GPF при выполнении из пользовательского режима. Я поместил его там и в основном забыл об этом. (Первоначально проблема была чем -то вроде переполнения буфера или ошибки распределения памяти)

Исправление: удалить hlt инструкция :) После удаления его, все работало гладко.

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

Лицензировано под: CC-BY-SA с атрибуция
scroll top