Pull to refresh

Гейзенбаг, или как Луна портит код

Reading time 6 min
Views 24K
Луна убывает, такое бывает… ©Земфира

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

heisenbug /hi:'zen-buhg/ n.
A bug that disappears or alters its behavior when one attempts to probe or isolate it.




Предлагаю вашему вниманию свою небольшую познавательную коллекцию квантовых эффектов в программировании.


Эпизод I, OpenOffice не печатает во вторник


Историю этого замечательного багрепорта можно почитать на Ubuntu Launchpad, а я вкратце изложу суть для тех, кому не сподручно читать по ссылке. В системной утилите file был баг из-за которого, файлы содержащие в 4-м байте Tue определялись как Erlang JAM. Дефект присутствовал в версиях file 4.21 и 4.24 и был вызван ошибкой в magic файле.


anon@x-X:~$ echo "1/2 Tue" >> file && file file
file: Jan 22 14:32:44 MET 1991\011Erlang JAM file - version 4.2
anon@x-X:~$ file --version
file-4.21
magic file from /etc/magic:/usr/share/file/magic

Это приводило к тому, что по вторникам для бажной версии file временные отметки PostScript файлов были похожи на Erlang JAM.


%%CreationDate: (Tue Mar 3 19:47:42 2009)

При отправке задания на принтеры семейства Brother, OpenOffice запускал процедуру проверки PostScript файла, которая завершалась ошибкой, потому что обнаруживала тип файла Erlang JAM. Исправление, в основном, свелось к экранированию пробела.


 +# 4.2 version may have a copyright notice!
-+4 string  Tue Jan 22 14:32:44 MET 1991    Erlang JAM file - version 4.2
-+79    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
++79    string  Tue\ Jan\ 22\ 14:32:44\ MET\ 1991   Erlang JAM file - version 4.2

Впрочем, и с бажным file проблема устранялась просто, однако к тому моменту гейзенбагу уже исполнилось 9 месяцев!


sed -e '/^%%CreationDate:/s/Tue/tue/' > $INPUT_TEMP

Эпизод II, Луна и Perl


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


Perl скрипт
#!/usr/bin/perl -w

use strict;
use warnings;

use constant PI => 3.1415926535;

use feature "say";

use SOAP::Lite;
use Astro::Coord::ECI::Moon;

my $soap = SOAP::Lite->uri('Debbugs/SOAP')->proxy('http://bugs.debian.org/cgi-bin/soap.cgi');

if (!defined($ARGV[0])) {
    die "E: must have a source package!\n";
}

my @bugs = $soap->get_bugs(src=>$ARGV[0])->result();

my $bugsdata = $soap->get_status(@bugs)->result();
my $moon = Astro::Coord::ECI::Moon->new();
my %count = ( 'new' => 0, 'first' => 0, 'full' => 0, 'last' => 0);

foreach my $bug (keys %$bugsdata) {
    my $time = $$bugsdata{$bug}->{date};
    my $phase = $moon->phase($time);
    if ($phase <= 45 * PI / 180 || $phase > 315 * PI / 180) {
        $count{'new'} = $count{'new'} + 1;
    } elsif ($phase <= 135 * PI / 180 && $phase > 45 * PI / 180) {
        $count{'first'} = $count{'first'} + 1;
    } elsif ($phase <= 225 * PI / 180 && $phase > 135 * PI / 180) {
        $count{'full'} = $count{'full'} + 1;
    } elsif ($phase <= 315 * PI / 180 && $phase > 225 * PI / 180) {
        $count{'last'} = $count{'last'} + 1;
    }
}

say "Number of bug submissions during new moon     : " . $count{new};
say "Number of bug submissions during first quarter: " . $count{first};
say "Number of bug submissions during full moon    : " . $count{full};
say "Number of bug submissions during last quarter : " . $count{last};

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


wouter@carillon:~code/perl$ ./debbugsmoon nbd
Number of bug submissions during new moon     : 2
Number of bug submissions during first quarter: 10
Number of bug submissions during full moon    : 1
Number of bug submissions during last quarter : 3

Для наукообразности можно даже в R проверить гипотезу функциональной зависимости. Данных маловато, но цифры внушают — p-value = 0.005853.


> chisq.test(c(2, 10, 1, 3));
    Chi-squared test for given probabilities

data:  c(2, 10, 1, 3)
X-squared = 12.5, df = 3, p-value = 0.005853

Предупреждение:
В chisq.test(c(2, 10, 1, 3)) :
  аппроксимация на основе хи-квадрат может быть неправильной

Я решил повторить эксперимент спустя 6 лет, и что бы вы думали?


[5153:23311 0:604] 06:09:39 Вс авг 28 [mikayel@redeye: +4] ~ 
(4:604)$ ./debbugsmoon.pl nbd
Number of bug submissions during new moon     : 1
Number of bug submissions during first quarter: 12
Number of bug submissions during full moon    : 3
Number of bug submissions during last quarter : 1

С этим nbd что-то явно не так, лунные фазы теперь давят сильнее!


> chisq.test(c(1, 12, 3, 1))
    Chi-squared test for given probabilities

data:  c(1, 12, 3, 1)
X-squared = 19.471, df = 3, p-value = 0.0002185

Предупреждение:
В chisq.test(c(1, 12, 3, 1)) :
  аппроксимация на основе хи-квадрат может быть неправильной

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


Эпизод III, Луна и LISP


Плохому танцору не всегда удаются сложные па, а программистам изредка гадит Луна. Нам об этом известно, благодаря хакерам старой школ, издавшем в 1983-м г. Словарь Хакера, у которого есть и другое название — the Jargon File. С тех пор книга выдержала еще несколько изданий и стала своего рода классикой жанра. В статье Phase of the Moon [1] есть довольно занятная байка на тему.


Однажды, Guy Steele [2], в то время еще студент MIT, словил баг в коде MacLisp [3], записывающей временные метки в отдельный файл содержащий формы, включив туда стандартную функцию приближенного вычисления фазы Луны. По неподтвержденным данным бажную программу также писал Gerry Sussman [4]. Изредка программа сбоила, причем случалось это каждый месяц в одно и то же время из-за того, что первая запись выкатывалась на новую строку, не обозначая комментарий символом ";". Длина первой записи зависела от временной метки и определенной фазы, то есть превышала широту страницы в 80 символов в зависимости от лунного календаря!


В той же статье упоминается еще один случай, когда в ЦЕРН сбоила программа обсчета результата экспериментов на ускорителе LEP коллайдера [5]. Долгие поиски причин сбоев наконец-то привели к разгадке. Кольцо периметра LEP, в 27 км. длиной, было очень незначительно деформировано из-за гравитации Луны. Эта история стала частью фольклора в среде физиков, получив название Ньютоново Возмездие. За достоверность деталей этой истории не могу поручиться, так как т. н. приливные деформации известны уже десятки лет как. Хотелось бы узнать мнение Хабра на этот счет.


Эпизод IV, мой Гейзенбаг


Был у меня на старом ноуте совершенно безумный баг, который приводил к полному или частичному зависанию ОС в время прослушивания музыки через USB наушники, причем чаще всего к зависанию приводило прослушивание интернет-радио. Я это терпел пару-тройку лет а затем, поняв, что ничего не меняется от смены версий ядра Linux, Xorg и драйверов, отправил багрепорт в Gentoo Bugzilla.


This happens for already 4 years with kernels starting 2.6.20 to 2.6.31. Similarly it happened on «HP nc 6220» based no intel chipset running «Debian Linux 5.x.» again USB headphones were Plantronics DSP 300.
Surprisingly it never happens under liveCD, I tested few times keeping audio-streaming for 1 hour and nothing crashed.


В вольном переводе, это жалоба на то, что гейзенбагу уже 4 года и он одинаково хорошо себя чувствует на версиях Linux ядра с 2.6.20 по 2.6.31, на чипсете AMD Radeon Xpress 200M и интеловском 915GM, но почему-то не прижился на LiveCD дистрибутивах.


В момент зависания нигде сообщения об ошибке не возникало и только в /var/log/messages появлялась запись: N URBs still active, где N — четное число < 10. Скорее всего падеж происходил в модуля ядра snd_usb_audio, небрежно обрабатывался и приводил систему в ступор.





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


Option "AccelMethod" "EXA" #было
Option "AccelMethod" "XAA" #стало

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




  1. Автор так обозначил разновидность Гейзенбага. По ссылке, the Jargon File, версия 4.3.3.
  2. Автор книги Common Lisp the Language, один из создателей языка програмимрования Scheme.
  3. Диалект языка программирования Lisp, разработанный в лаборатории искусственного интеллекта MIT.
  4. Один из создателей языка программирования Scheme, со-автор книги Structure and Interpretation of Computer Programs.
  5. Большой электрон-позитронный коллайдер.
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+35
Comments 86
Comments Comments 86

Articles