Подтвердить что ты не робот

Какие ошибки WONTFIX на GNU/Linux и как их обойти?

Как Linux, так и пользовательское пространство GNU (glibc), похоже, имеют множество ошибок WONTFIX, то есть ошибки, которые ответственные стороны заявили о своем нежелании исправлять, несмотря на явно нарушающие требования ISO C и/или POSIX, но я "Не зная о каком-либо ресурсе для программистов, который перечисляет такие ошибки и предложения для работы вокруг них.

Вот некоторые из них, которые приходят на ум:

  • Ошибка UDP Linux select: select (и связанные с ней интерфейсы) указывает дескриптор файла сокета UDP, готовый для чтения, как только пакет получен, без подтверждения контрольной суммы. В последующих recv/read/и т.д., Если контрольная сумма была недействительной, вызов блокируется. Для этого необходимо всегда устанавливать UDP-сокеты в неблокирующий режим и работать с условием EWOULDBLOCK. Если я правильно помню, MaraDNS был первым заметным проектом, затронутым этой ошибкой, и первым пожаловал (безуспешно), чтобы он исправил. Примечание: Как указывал Мартин против Льюиса, эта ошибка с тех пор была исправлена. Обходные пути, вероятно, необходимы только в том случае, если вам необходимо поддерживать действительно устаревшие версии Linux.
  • Семейство printf в библиотеке GNU C неправильно интерпретирует аргументы %s как многобайтовые символьные строки вместо строк байтов, когда задана точность поля (как в %.3s), что потенциально вызывает усеченный вывод. Я не знаю обходного пути, кроме замены всей подсистемы printf (или просто не использующей семейство функций printf с строками байтов без мультибайтовых символов, но это может быть проблематично, если вы хотите обработать строки устаревшей кодовой страницы, используя snprintf в то время как в локали UTF-8).
  • Неверный errno код результата для некоторых системных вызовов (не помню, какие из них сразу). Обычно их достаточно просто проверить, если вы просто прочитали справочные страницы GNU/Linux и сравните их со стандартом. (Я не могу найти ссылки для этого и, возможно, ошибаюсь. Ближайшее, что я могу найти, это выпуск ENOTSUP и EOPNOTSUP с тем же значением, см. PDTR 24715.

Какие еще ошибки и обходные пути мы можем добавить в этот список? Мои цели в задании этого вопроса:

  • Чтобы создать более полный список таких ошибок, чтобы как новые, так и опытные программисты могли быстро узнать о потенциальных проблемах, которые могут возникнуть при запуске программы, предназначенной для переноски, в GNU/Linux.
  • Чтобы использовать коллективный мозг SO, чтобы придумать умные и ненавязчивые стандартные обходные пути для как можно большего числа таких ошибок, вместо того, чтобы каждый мог придумать свои собственные методы обхода после того, как их укусили, и, возможно, сделать это в субоптимальных, уродливых или хакерских способах - или, что еще хуже, способами, которые нарушают поддержку более совместимых систем.
4b9b3361

Ответ 1

Я не могу воспроизвести проблему с printf, которую вы требуете. Запуск программы

#include <stdio.h>
#include <locale.h>

int main()
{
        setlocale(LC_ALL, "");
        printf("%.4s\n", "Löwis");
        return 0;
}

в дереве de_DE.UTF-8 печатает "Löw", который выглядит прямо на меня: я попросил 4 байта и получил четыре байта (ö - 2 байта). Если бы библиотека учитывала многобайтовые символы, выход должен был быть "Löwi". Это с glibc 2.11.2.

Изменить. Изменение строки до "%.2s\n" будет просто печатать "L", то есть только один байт. Однако это соответствует спецификации, в которой говорится

Если задана точность, не более чем, что должно быть записано много байтов.

(выделение мое), а затем

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

Итак, поскольку печать двух байтов (то есть L и ведущего байта ö) приведет к написанию частичного символа, это будет несоответствие печатать неполное UTF-8.

Ответ 2

Я не считаю, что проблема UDP действительно существует. В текущем ядре Linux udp_poll читает

/**
 *      udp_poll - wait for a UDP event.
 *      @file - file struct
 *      @sock - socket
 *      @wait - poll table
 *
 *      This is same as datagram poll, except for the special case of
 *      blocking sockets. If application is using a blocking fd
 *      and a packet with checksum error is in the queue;
 *      then it could get return from select indicating data available
 *      but then block when reading it. Add special case code
 *      to work around these arguably broken applications.
 */
unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
{
        unsigned int mask = datagram_poll(file, sock, wait);
        struct sock *sk = sock->sk;

        /* Check for false positives due to checksum errors */
        if ((mask & POLLRDNORM) && !(file->f_flags & O_NONBLOCK) &&
            !(sk->sk_shutdown & RCV_SHUTDOWN) && !first_packet_length(sk))
                mask &= ~(POLLIN | POLLRDNORM);

        return mask;

}

Поэтому мне кажется, что он скрывает UDP-пакеты с плохими контрольными суммами от сообщения через select/poll. Эта версия кода используется с момента пересмотра 85584672 (2009). Но даже раньше (по крайней мере, с 2005 года) код, по-видимому, уже делал то же самое, что и отбрасывать плохие пакеты в select/poll.