86 выпуск новостей проекта ReactOS

Доступен перевод 86 выпуска новостей проекта ReactOS, операционной системы с открытым исходным кодом, нацеленной на обеспечение совместимости с программами и драйверами Microsoft Windows семейства NT (XP/2003).

Прогресс в использовании компилятора MSVC

Код ReactOS теперь может быть полностью собран с использованием компилятора Microsoft, но работать после такой компиляции операционная система пока ещё не способна. Тимо Кройцер (Timo Kreuzer) уже устранил несколько ошибок, среди которых повреждение метаданных файловой системы, приводившее к неработоспособности загрузчика freeldr. На платформах x86/x64 в процессе начальной загрузки в таблицу FAT c диска считывается загрузочный сектор, который должен быть загружен в достаточно высокие адреса, чтобы дальнейшее чтение freeldr в память позже не перезаписало бы эту таблицу. К сожалению, скомпилированная в MSVC версия freeldr занимает больше места, чем при компиляции с использованием GCC, что приводило к перезаписи таблицы FAT. Когда начальный загрузчик пытался запросить таблицу FAT, чтобы понять, нужно ли загрузить ещё что-то, он получал код freeldr вместо данных и предполагал, что необходимо загрузить дополнительные данные. Однако попытка использовать данные freeldr в качестве инструкции по загрузке, приводила к выводу ошибки и невозможности загрузить freeldr. Тимо устранил эту проблему, изменив адреса, куда загружается таблица FAT, чтобы гарантировать цельность данных при использовании файлов, скомпилированных с помощью MSVC.

Другая проблема, связанная с файловой системой, была найдена в драйвере именованного канала (pipe). Драйвер поддерживает связанный список клиентских блоков управления (CCB), доступ к которому синхронизируется с использованием блокировки (lock). Однако существовал способ получить доступ к CCB без установки блокировки, что могло привести к эффекту гонки (race condition). Например, при определенном стечении обстоятельств один поток мог удалить запись в списке CCB, но ссылка на этот удаленный элемент могла в это время использоваться в другом потоке. Решение Тимо состояло в использовании счетчика ссылок, с последующим отслеживанием числа активных экземпляров ссылок к элементам CCB, чтобы препятствовать удалению еще занятых элементов CCB. Эта проблема также существовала и в сборке GCC, но была более достоверно воспроизведена в сборке MSVC.

Устранение ошибок сети

Хрупкость сетевого стека ReactOS иногда трудно понять не-разработчикам, но список проблем, который был недавно разрешен Камероном Гутманом (Cameron Gutman), должен дать представление о том, как много частей работало неправильно. Камерон обратил свое внимание на то, что многие сетевые тесты завершаются провалом. В результате трассировки некоторых сбойных тестов было выявлено использование некорректной семантики при работе с кодом обработки событий. Если программа сообщает ОС, что она ожидает определенное событие, но событие при этом было уже инициировано или инициировано прежде, чем ОС фактически вызывает функцию ожидания, ОС, как предполагается, сразу запускает программу, как только будет выполнен вызов ожидания события. Это не было сделано, что приводило к тому, что запрашивающие уведомление о событии программы в некоторых ситуациях зависали, прежде, чем могли сделать что-либо еще.

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

Помимо уведомления о событиях сетевой активности, было найдено несколько серьёзных семантических ошибок в обработке соединения TCP, реализованных в некоторых частях сетевого стека. Функции recvfrom и sendto обрабатывали соединения TCP так, как если бы они были соединениями UDP. Достаточно сказать, что это просто никак не работало. Единственной причиной, по которой данная ошибка не затронула большинство пользователей, является немногочисленность приложений, использующих функции recvfrom и sendto с соединениями TCP, вместо которых обычно используются функции recv и send. Как ни парадоксально, recv работал неправильно с соединениями UDP, и снова ошибки не возникали только потому, что большинство приложений использует для UDP функцию recvfrom. Исправление должно помочь справится с теми случаями, когда приложения не соблюдали выше описанные негласные правила.

Еще один набор проблем был связан с особенностями завершения работы сетевых соединений в используемой в ReactOS библиотеке oskittcp. Протокол «рукопожатия» (handshake) в TCP предусматривает использование пакетов с флагом FIN для информирования удаленной стороны о завершении передачи данных. Вызов функции «shutdown(SD_SEND)» генерирует пакет FIN, но должен все еще оставить соединение открытым для чтений. К сожалению, библиотека oskittcp не делала этого и полностью закрывала сокет, что приводит к невозможности выполнения операций чтения из сокета после вызова функции завершения отправки данных. Заключительная проблема, которую устранил Камерон, также была связана с oskittcp. В частности, из-за данной библиотеки не происходило информирование ОС о сбоях соединения. После решения данной ошибки сетевой стек ReactOS проходит значительно больше тестов и стал более пригоден к использованию. Одновременно, проблемы в oskittcp подталкивают разработчиков к миграции на альтернативную библиотеку lwip.