Одна ракета, четыре спутника, ноль шансов — и переменная, которая не поместилась в отведённую ей клетку.
4 июня 1996 года, экваториальная Французская Гвиана, космодром Куру. Влажный воздух, температура за тридцать, и на стартовом столе — машина, в которую вложено десять лет работы. Ariane 5 — первый европейский тяжёлый носитель нового поколения, способный выводить на орбиту вдвое больше предшественницы, Ariane 4. Внутри головного обтекателя — четыре одинаковых спутника миссии Cluster, каждый весом около 1200 килограммов, каждый начинён магнитометрами, детекторами частиц и волновыми анализаторами. Замысел Европейского космического агентства был элегантен: четыре аппарата, летящие тетраэдром сквозь магнитосферу Земли, впервые позволят отличить пространственные структуры солнечного ветра от временных — то, чего одиночный спутник принципиально сделать не может. Всё было готово, обратный отсчёт дошёл до нуля, и твердотопливные ускорители выдали свои тысячи тонн тяги.
Ракета поднялась. На записях видно, как она идёт ровно, почти красиво — первые тридцать с лишним секунд. А потом Ariane 501 (так обозначался этот первый экземпляр) резко дёрнулась, начала разворачиваться боком к набегающему потоку, и аэродинамические нагрузки стали разрушать конструкцию. На высоте примерно четырёх километров сработала система самоликвидации — и офицер безопасности полёта, и автоматика подтвердили команду на уничтожение. Обломки, спутники и несостоявшееся будущее европейской магнитосферной физики рассыпались над болотами Гвианы. Отказ инерциальных систем зафиксирован на 36,7-й секунде полёта; сам разворот и разрушение — на тридцать девятой. Весь полёт длился меньше сорока секунд.
Расследование заняло несколько недель. Комиссию возглавил Жак-Луи Лионс, французский математик, и её отчёт — один из самых цитируемых документов в истории программной инженерии. Цепочка отказов была восстановлена с хирургической точностью.
Сердце навигации Ariane 5 — инерциальная референсная система, SRI (Système de Référence Inertielle). Она измеряет ускорения и угловые скорости, вычисляет положение ракеты в пространстве и передаёт данные бортовому компьютеру. На борту стояли две идентичные SRI — основная и резервная, — и обе работали на программном обеспечении, которое в значительной части было унаследовано от Ariane 4. В этом коде существовала функция выравнивания (alignment), которая калибровала инерциальную платформу на стартовом столе и продолжала работать ещё около 40 секунд после старта. Внутри этой функции горизонтальная скорость ракеты, обозначенная как переменная BH, вычислялась как 64-битное число с плавающей точкой, а затем преобразовывалась в 16-битное знаковое целое. Диапазон 16-битного знакового целого — от −32 768 до +32 767. На Ariane 4 горизонтальная скорость в первые секунды полёта никогда не приближалась к этим границам: ракета стартовала медленнее и по другой траектории. На Ariane 5 — приблизилась и перешагнула.
Когда значение BH вышло за пределы допустимого диапазона, процессор выбросил исключение — Operand Error. Программа не содержала обработчика для этого конкретного исключения в этой конкретной переменной. Почему? Потому что при разработке ПО для Ariane 4 был проведён анализ, показавший: физически невозможно, чтобы BH достигла таких значений в условиях полёта этой ракеты. Защиту сняли сознательно, чтобы сэкономить вычислительные ресурсы процессора. Решение было корректным — для Ariane 4. Для Ariane 5 его никто не пересмотрел.
Резервирование — священный принцип космической техники. Если один блок отказывает, второй подхватывает управление. На Ariane 501 резервная SRI отказала на 72 миллисекунды раньше основной — по той же самой причине, в той же самой строке кода. Обе системы были программными копиями друг друга, обе выполняли ту же ненужную после старта функцию выравнивания, обе наткнулись на то же переполнение. Резервирование, которое должно было спасти полёт, оказалось фикцией: это была не избыточность, а удвоение одной и той же уязвимости.
Меня завораживает этот момент — 72 миллисекунды между двумя одинаковыми смертями. Разница возникла только из-за мельчайших различий в синхронизации тактов процессоров. Архитектурно системы были тождественны. Ни одна из них не могла компенсировать ошибку другой, потому что ошибка была не аппаратной, а логической, и была вшита в обе с одинаковой неизбежностью.
Дальше случилось нечто, что превращает аварию из просто программного сбоя в системную катастрофу. Когда SRI обнаруживала фатальную ошибку, она прекращала нормальную работу и передавала по штатному каналу связи диагностическое сообщение — по сути, код ошибки и состояние регистров процессора. Бортовой компьютер OBC (On-Board Computer) не имел механизма для того, чтобы отличить это диагностическое сообщение от нормальных навигационных данных. Он принял набор битов, описывающих внутреннее состояние умирающего процессора, за команды на отклонение сопел. Числа были большими — и сопла отклонились на максимальный угол. Ракета, шедшая вертикально вверх, получила команду на резкий поворот, аэродинамика сделала остальное.
Легенда гласит: «ракету погубила одна строка кода». Это удобная формулировка, но она прячет главное. Строка кода — преобразование типа данных — была технически корректна в рамках своей исходной системы. Её написали для Ariane 4, проверили для Ariane 4, и она безупречно работала на протяжении десятков успешных полётов. Катастрофу вызвала не строка, а цепочка организационных решений, каждое из которых по отдельности выглядело разумным.
Первое допущение: программное обеспечение SRI можно перенести на новый носитель без полной ревалидации. Ariane 5 отличалась от Ariane 4 радикально — другие двигатели, другая тяговооружённость, другой профиль набора скорости. Но SRI «уже летала», и это создавало иллюзию проверенности. По сути, инженеры перенесли зимнюю резину на гоночный болид, потому что «резина же проверенная».
Второе допущение: функция выравнивания, нужная только до старта, может безопасно продолжать работу после отрыва от стола. На Ariane 4 эту функцию оставляли включённой ещё на некоторое время после старта по практической причине — на случай аварийной остановки обратного отсчёта и перезапуска. Решение перекочевало в Ariane 5 по инерции. Никто не задал вопрос: а зачем функция предстартового выравнивания работает, когда ракета уже летит?
Третье допущение: если обе SRI отказывают, бортовой компьютер всё равно получит осмысленные данные. Протокол связи между SRI и OBC не предусматривал маркировки сообщений как «диагностика» или «навигация». Данные шли по одному каналу, в одном формате. Это архитектурное решение означало, что любой мусор, попавший в канал, будет интерпретирован как команда.
Четвёртое допущение: резервирование обеспечивает надёжность. Две идентичные системы с идентичным программным обеспечением защищают от аппаратных сбоев — отказа платы, перегрева, скачка напряжения. От логической ошибки, заложенной в код обеих систем, они не защищают вообще. Настоящая избыточность потребовала бы двух разных реализаций одного и того же алгоритма, написанных разными командами, — подход дорогой и редко применяемый в полном объёме.
Каждое из этих допущений имело свою логику. Ни одно не было результатом халатности или некомпетентности. Но вместе они образовали коридор, в котором единственное переполнение переменной превратилось в потерю ракеты.
Контрфактическая история — жанр скользкий, и я не хочу делать вид, будто знаю альтернативное будущее. Но кое-что можно сказать с высокой степенью уверенности.
Если бы Ariane 501 отлетала штатно, четыре спутника Cluster вышли бы на свои орбиты летом 1996 года. Миссия была спроектирована для работы в составе квартета: каждый аппарат измерял одни и те же физические параметры, но в разных точках пространства, и именно разница между четырьмя одновременными замерами позволяла реконструировать трёхмерную структуру магнитосферных токов, ударных волн и пересоединений магнитных силовых линий. Эта методика — многоточечные измерения in situ — была к тому моменту теоретически обоснована, но ни разу не реализована на практике.
Вместо этого ESA оказалось перед выбором: отказаться от научной программы или строить всё заново. Решение о восстановлении миссии под названием Cluster II было принято примерно через десять месяцев после катастрофы. Четыре новых спутника были изготовлены, но запускались уже не на Ariane 5, а парами на российских ракетах «Союз» с Байконура — в июле и августе 2000 года. Стоимость программы Cluster II составила 214 миллионов ЭКЮ. Первые данные четырёхточечных измерений магнитосферы, ради которых всё затевалось, пошли с задержкой примерно в четыре года относительно первоначального графика.
Четыре года в науке о космической погоде — это много. Солнечная активность циклична, период около одиннадцати лет, и каждый упущенный год солнечного максимума или минимума — это данные, которые не собраны и не могут быть собраны задним числом. Cluster II в итоге проработала блестяще, намного дольше запланированного срока, и произвела сотни научных статей. Но те конкретные условия магнитосферы, которые существовали в 1996–2000 годах, остались неизмеренными четырёхточечным методом навсегда.
Успешный дебют Ariane 5 сам по себе не превратил бы её мгновенно в доминирующий коммерческий носитель. Рынок пусковых услуг в конце 1990-х определялся ценой, надёжностью послужного списка и доступностью слотов запуска. Одна удачная миссия — это начало статистики, а не её замена. Но репутационный удар от публичного уничтожения ракеты на первом же полёте был серьёзен: заказчики коммерческих спутников предпочитают носители с историей успехов, и Ariane 5 пришлось эту историю выстраивать с нуля, с отрицательного старта. Второй полёт состоялся только в октябре 1997 года, и тоже с частичным отклонением от расчётной орбиты — хотя и без потери полезной нагрузки.
Программист, написавший преобразование типа данных для переменной BH, не совершил ошибки. Он написал код, соответствующий спецификации Ariane 4, в которой физический диапазон горизонтальной скорости гарантированно укладывался в 16 бит. Инженер, снявший защиту от переполнения, действовал в рамках обоснованного анализа — на Ariane 4 переполнение было физически невозможно, а обработка исключений стоила процессорного времени, которое на бортовых вычислителях 1980-х годов было дефицитом. Архитектор, решивший повторно использовать проверенное ПО, руководствовался здравым инженерным консерватизмом: зачем переписывать то, что работает?
Проблема была не в людях и не в коде. Проблема была в зазоре между двумя контекстами — старым и новым — и в отсутствии процедуры, которая заставила бы кого-то этот зазор систематически проверить. Комиссия Лионса указала на это прямо: ПО было повторно использовано без адекватного анализа его поведения в новых условиях полёта. Независимая верификация, которая могла бы выявить несоответствие, по грубому говоря, не добралась до этого уровня детализации.
Меня поражает, насколько этот механизм универсален. Он не специфичен для ракет. Любая сложная система, собранная из компонентов, проверенных в одних условиях и перенесённых в другие, несёт в себе ту же угрозу. Код не портится — портится его соответствие реальности. И чем успешнее компонент работал в прошлом, тем меньше желания его перепроверять, тем толще слой доверия, через который должен пробиться тревожный сигнал.
После катастрофы Ariane 501 отчёт комиссии стал обязательным чтением в программах подготовки инженеров по всему миру — от Тулузы до Пасадены. Случай вошёл в учебники по надёжности ПО, по системной инженерии, по управлению рисками. Но он вошёл туда не как история про «плохую строку кода», а как история про организацию, которая не задала правильный вопрос в правильный момент. Ракету уничтожило не переполнение целого числа. Ракету уничтожило предположение, что проверенное в одном мире останётся проверенным в другом, — предположение настолько естественное, что его даже трудно заметить, пока обломки не лежат в болоте.
Cluster II, к слову, дожила до финального жеста: в сентябре 2024 года ESA намеренно свела с орбиты аппарат Salsa — почти четверть века вместо запланированных двух лет, — и данные с этих четырёх спутников до сих пор анализируются в десятках лабораторий. Наука в итоге получила своё, но получила с опозданием, с удвоенными затратами и на чужих ракетах.