Попытка использовать xautolock для приостановки активности через определенное время

Мне удалось воспроизвести эту проблему в Ubuntu 17.10 (glibc 2.26 )и в Ubuntu 18.04 (glibc 2.27 ), но похоже, что она исправлена ​​в Ubuntu 18.10 (glibc 2.28)

Проблема связана с локальными данными, точнее с данными LC _COLLATE для en _US.utf8 (,что данные сопоставления поступают из файла ISO 14651, который включен в большинство локалей, поэтому, вероятно, он влияет и на все другие локали utf8.)

Локальные данные получены из glibc, и ошибка, кажется, присутствует там (, хотя дистрибутивы довольно сильно настраивают эти данные, так что, возможно, другие дистрибутивы с glibc

На самом деле, объявление glibc 2.28 начинает список новых функций с:

The localization data for ISO 14651 is updated to match the 2016 Edition 4 release of the standard, this matches data provided by Unicode 9.0.0. This update introduces significant improvements to the collation of Unicode characters.

Глядя на коммиты, можно заметить, что локальные данные сильно переработаны, так что, вероятно, это исправило ошибку!

Короче говоря, проблема сопоставления этих двух символов (U0030, что означает «0», и U0660, что является арабским -индийским нулем «٠» ), заключается в том, что они сортируются точно так же., при сравнении с использованием strcoll (3 ), что можно продемонстрировать с помощью этого короткого теста с использованием sort(, который использует strcollпод капотом):

ubuntu-18.04$ { echo 0; echo -e '\u0660'; echo 0; } | sort
0
٠
0

И на glibc 2.28:

ubuntu-18.10$ { echo 0; echo -e '\u0660'; echo 0; } | sort
0
0
٠

Как видите, в более старой версии glibc не происходит переупорядочения арабского -индийского нуля '٠' ни до, ни после '0', что доказывает, что они сопоставляются одинаково.

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

В исходных текстах glibc 2.27 для ISO 14651 можно найти следующие определения:

 <0>;;;IGNORE # 171 0
 <0>;;;IGNORE
 <0>;;;IGNORE
 <0>;"";"";IGNORE

Таким образом, как '0' (\u0030), так и '٠'(\u0660)расширяются до одной и той же последовательности (<0>;;;IGNORE), что означает, что strcollбудет относиться к ним одинаково. (Это также объясняет, почему другие символы, такие как \u06f0и \u0966, не затрагиваются, так как их расширение отличается.)

Глядя на исходные коды glibc 2.28 для ISO 14651 , можно найти следующие определения:

 ;;; % DIGIT ZERO
 ;;; % ARABIC-INDIC DIGIT ZERO
 ;;; % EXTENDED ARABIC-INDIC DIGIT ZERO
 ;;; % NKO DIGIT ZERO
 ;;; % DEVANAGARI DIGIT ZERO

Четвертое поле теперь всегда заполняется самой кодовой точкой, что означает, что они будут иметь определенный порядок сортировки, даже если первые несколько полей совпадают.Хотя изменение для не было введено в этой конкретной фиксации , его описание объясняет идею:

[...] putting the code point of the character into the fourth level instead of “IGNORE”. Without that change, all such characters would compare equal which would make a wcscoll test case fail. It is better to have a clearly defined sort order even for characters like this so it is good to use the code point as a tie-break.

  • localedata/locales/iso14651_t1_common: Use the code point of a character in the fourth collation level instead of IGNORE for all entries which have IGNORE on all 4 levels.

Надеюсь, это объясняет ошибку с локальными данными в glibc


Что касается bash, если вы посмотрите на исходный код , вы увидите, что он обрабатывает один символ(0)в выражении в квадратных скобках([0])так же, как если бы это был диапазон с символ как начало и конец([0-0]):

cstart = cend = FOLD (cstart);

Затем он сравнивает текущий символ с этим диапазоном , используя RANGECMP:

if (RANGECMP (test, cstart, forcecoll) >= 0 && RANGECMP (test, cend, forcecoll) <= 0)
  goto matched;

И затем RANGECMP (, определенный как rangecmp_wcв многобайтовом режиме -), использует wcscall (3 )(, который является многобайтовой версией strcoll -):

return (wcscoll (s1, s2));

Тот факт, что bash использует сравнение диапазона для одного символа (в качестве ярлыка, чтобы разделить часть кода с обработкой диапазонов ), делает его таким, что он также принимает все символы, которые сортируются одинаково. как оригинальный персонаж.

Другие оболочки, вероятно, не имеют этой проблемы, потому что они выполняют прямое сравнение, если диапазон не задействован.

Причина, по которой эта проблема начала появляться в bash 3.0, заключается в том, что в bash 3.0 появилась поддержка мульти -байт (Unicode ), что привело к рефакторингу всего этого кода и, возможно, к использованию сравнений с учетом локали -. которые связаны с проблемой.

ОБНОВЛЕНИЕ:Об этой проблеме сообщил как об ошибке в проекте bash @Isaac .


ВРЕМЕННОЕ РЕШЕНИЕ:Если обновление до дистрибутива, использующего glibc 2.28, невозможно, можно использовать LC_COLLATE=C.utf8или POSIX.utf8, которые определяют «тривиальный» порядок сортировки, при котором никакие кодовые точки не будут сортироваться одинаково. Учитывая, что проблема связана с сопоставлением, достаточно установить только LC_COLLATE. Тестирование этого обходного пути на Ubuntu 17.10 и 18.04 показало, что этого достаточно, чтобы решить эту проблему.

1
03.12.2020, 12:12
0 ответов

Теги

Похожие вопросы