flang компилятор доказывает, что программа не зациклится 0.6.2 GitHub

Пустая строка у «Прочитано» значит КОНЕЦ, и раскодировщик, вызванный руками, отдаёт её ещё в одном случае

Ловушка, в которую я попал за десять минут после правки, и поймала её проверка, а не чтение кода.

В словаре ввода-вывода пустая строка у отклика «Прочитано» значит конец связи — по ней программа отличает обрезанный запрос от недочитанного. Пока хозяин на Node пользовался сокет.setEncoding("utf8"), другого случая пустой строки не возникало: поток сам не выдаёт события с пустым куском, то есть ждал за нас.

Стоило заменить setEncoding на StringDecoder, вызываемый руками, — и появился второй случай: пришёл кусок, целиком состоящий из НАЧАЛА многобайтовой последовательности. Раскодировщик придерживает его и возвращает пустую строку. Отдать её программе значило бы соврать «связь кончилась» на первой же кириллической букве, порезанной границей пакета TCP.

Правило шире случая: всякий раз, когда пустое значение уже что-то значит в контракте, механизм, способный вернуть пустое по другой причине, обязан ждать или называть свою причину отдельно. Тот же вид беды, что и часовое значение в поле: два разных смысла в одном представлении, и разбор их не различает.

Чем подтверждено. Ветка vypusk/hozyain, коммит b48a5a9. Проверка «ПРОВЕРКА ИМЕЕТ ЗУБЫ: разрез, на котором сломанный раскодировщик покраснел бы» в flang/test/oktety.test.mjs: слово «ёжик» отдаётся сервером по одному октету на пакет; без ожидания программа получает пустую строку вместо слова, то есть видит конец связи на первом же октете.

Чем ограничено. Ожидание стоит в текстовом чтении и только в нём: у октетного хвоста нет — половинки октета не бывает, — и там пустой список по-прежнему значит ровно конец.

Связано: octets-are-expressible-as-a-list-of-numbers-not-as-a-string, checks-that-stopped-comparing