Какие ошибки 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, чтобы придумать умные и ненавязчивые стандартные обходные пути для как можно большего числа таких ошибок, вместо того, чтобы каждый мог придумать свои собственные методы обхода после того, как их укусили, и, возможно, сделать это в субоптимальных, уродливых или хакерских способах - или, что еще хуже, способами, которые нарушают поддержку более совместимых систем.
Ответы
Ответ 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.