Алексей Махоткин

домашняя страница

Художественная хирургия

Моя любимая история о рефакторинге продакшена из книги Е. В. Кудрявцева «Техника реставрации картин», Издательства Государственной Третьяковской Галлереи [sic!], Москва, 1948 год.

[Partial attacks] с утра весь день я открываю кассу каждые десять минут и перебираю вчерашнюю выручку — шорох и звон успокаивают. дверь с грохотом распахивается, дрожит стекло и меня снова охватывает сострадание: я слышу знакомый запах старого немытого больного тела, засохшей крови, трясущихся рук, перегара, слезящихся глаз, корицы, раскаленного стекла, яблок, соли, железный привкус во рту, тусклая зарешеченная лампа в длинном пустом коридоре, в моих легких уже много лет гниёт болотная вода, и стая птиц снимается с проводов, напуганная далеким взрывом.

Engineering/DevOps блоги

Во-первых, агрегатор разнообразного контента, сфокусированный на scalability: HighScalability.com.

Во-вторых, блоги крупных технологических компаний:

В-третьих, также рекомендуется мудрый твиттер DEVOPS_BORAT.

Номер ревизии в Git

В Subversion есть полезная в некоторых случаях вещь — монотонно увеличивающийся номер ревизии.

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

git log --pretty=oneline | wc -l

которая выдаст число коммитов, предшествующих текущему.

Чтобы добавить к этому номеру уникальность, можно конкатенировать его с текущим sha1 — тогда на разных ветках будут разные номера ревизий.

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

Bash History в терминале Mac OS X

Для Mac OS X оказалось очень удобно поместить в ~/.bash_profile две строчки:

export HISTFILE=~/.bash_history-`tty | sed -e 's/\/dev\///'`
export HISTCONTROL=ignoreboth

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

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

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

Полезный пример использования Git Stash и Git Diff

В посте ”The second-order-diff Git trick” излагается полезный пример использования git stash.

Вносим массовые изменения в дереве. Если все ок, то делаем git commit, если не все ок — то делаем git stash (а вовсе не git reset, как сделали бы многие). Состояние дерева откатывается до исходного. Вносим исправленные массовые изменения в дереве. Теперь мы можем сказать git diff stash@{0} и увидеть, чем отличаются друг от друга два результата массовых изменений.

Trinity: Fuzz-тестирование системных вызовов Linux

Очень интересный проект Trinity предназначен для fuzz-тестирования системных вызовов ядра Linux.

Каждый системный вызов аннотирован информацией об аргументах системного вызова — например, является ли аргумент набором флагов, адресом памяти или номером файлового дескриптора. При работе Trinity генерирует случайные входные данные для каждого известного syscall, и вызывает его. Так как структура аргументов известна, то эффективность тестирования существенно выше, чем при использовании наивного тестирования, которое просто генерирует случайные числа и скармливает их ядру. Например, можно особое внимание уделить адресам памяти, которые находятся рядом с четырехкилобайтными границами страниц, чтобы отлавливать ошибки off-by-one.

Практика, описанная в статье ”LCA: The Trinity fuzz tester” на прекрасном ресурсе LWN.net, демонстрирует интересные результаты. За 2012 год только сам автор обнаружил больше 150 багов в ядре. Еще больше багов нашли другие пользователи системы. Помимо багов в коде системных вызовов, были обнаружены различные проблемы с сетевой и дисковой подсистемами, а также в многочисленных драйверах. При тестировании системного вызова execve также можно очень быстро обнаружить множество ошибок в системных утилитах, которые запускаются со случайными аргументами командной строки (и падают от того).

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

Кабаний лес

Один из эпизодов романа Ши Найаня «Речные заводи». Обработка Ши Хуана. Рисунки Бу Сяо-хуая.

Издательство литературы на иностранных языках. Пекин, 1960 г. Отпечатано в Китайской Народной Республике.

PDF: kaban.pdf

PDF Metadata в Unicode

Метаданные (такие, как Author, Title и т. п. — видны в Document Properties) в стандарте PDF хранятся в совершенно ужасном формате.

Например, информация об авторе будет записана так:

/Author (...)

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

Если ваша строка помещается в Latin1, то достаточно записать вместо многоточия сроку в этой кодировке, нужно только искейпить (добавив backslash) как минимум скобки и backslash (tiff2pdf искейпит еще несколько символов: возможно, от ужаса или для обратной совместимости неизвестно с чем).

Если ваша строка требует более полного Unicode, то вам придется сконструировать байтовую строку, состоящую из: а) BOM (Byte-Order Mark) в big-endian UTF-16; б) собственно текста в big-endian UTF-16. После этого нужно еще раз пройтись по этой байтовой строке, и искейпить в ней скобки и backslash (да, прямо «внутри» UTF-16BE). Полученную байтовую строку можно поместить внутрь скобок.

Удивительно здесь, что стандарт требует big endianness, и одновременно с этим требует указывать BOM. Казалось бы — с помощью BOM можно было бы совершенно стандартно поддержать UTF-16BE, UTF-16LE и UTF-8!

Я написал несколько патчей, которые исправляют поддержку Unicode в tiff2pdf.