LINUX.ORG.RU

Замещение LF -> CRLF в терминале

 


0

1

Всем привет! Есть некоторая программа1 на си, которая обрабатывает команды от оператора в терминале линукса, отправляет их программе2 на эрланге и получает ответ в виде строки «event1\event2\nevent3\n...eventN». Далее эта строка записывается в stdout:

fwrite(ERL_BIN_PTR(data), 1, size, stdout);

И оператор должен увидеть красивый построчный вывод команды в терминале. И всё бы хорошо, но почему-то периодически пара строк перетирается последующими строками. Всего в выводе больше 200 строк, но перетираются только две конкретные. Насколько я себе это представляю, терминал должен заменять LF-символ (\n) на CRLF (это описано на вики http://en.wikipedia.org/wiki/Line_discipline). Однако, для упомянутых выше строк вставляется только CR, благодаря чему каретка не переводится вниз, и следующая строка печатается поверх текущей. Причем, если перенаправить вывод в файл, или грепать эту строку, то всё отображается полностью. Кто-то сталкивался с подобным? Есть еще вариант посмотреть побайтово, что программа1 получает от эрланга. Возможно, я просто не вижу в редакторе некоторые специальные символы, которые ломают вывод, но более вероятным кажется, что проблема в терминале.

Посмотри побайтово.

Сколько тысяч строк не выводил, никогда с таким не сталкивался

Вместо sh пробовал bash, dash, ksh?

Adonai ★★★
()
Последнее исправление: Adonai (всего исправлений: 1)

И всё бы хорошо, но почему-то периодически пара строк перетирается последующими строками.

Программа у тебя однопоточная?

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

Да у него скорее всего просто stderr еще срет в консольку параллельно с stdout, вот такая шарманка и получается.

Eddy_Em ☆☆☆☆☆
()

для упомянутых выше строк вставляется только CR

Вы в этом уверены, или это Ваше предположение?

Sorcerer ★★★★★
()
Ответ на: комментарий от Adonai

Вместо sh пробовал bash, dash, ksh

Не пробовал

Программа у тебя однопоточная?

Однопоточная

Да у него скорее всего просто stderr еще срет в консольку

Ничего лишнего в консоли не вижу

Вы в этом уверены, или это Ваше предположение?

Ммм... я их руками не щупал, и не уверен насколько корректно редакторы отображают эти символы. Но если этот вывод сохранить командой script в файл typescript, а потом открыть (при простом перенаправлении в файл получится корректный вывод) в nedit - там после каждой строки отображаются символы <CR>, а после искомой строки - <CR>, и сразу следующая строка печатается без переноса. Если открыть Notepad++ в винде - то отображаются везде <CR><LF>, после искомой строки - только <CR>.

Попробую сегодня побайтово проверить

ignoramus8
() автор топика
Ответ на: комментарий от Elyas

Про size можно было бы предположить, если бы ломалось всё именно в конце вывода.

Попробовал проанализировать побайтово кусок двух строк, которые одна на другую накладываются - там всё корректно, между ними один символ с кодом 10 ('\n') всегда. В попыках локализовать баг, проверил кучу бредовых и не очень идей. Остановился на том, что если данные, полученные от эрланга выводить в цикле 10 раз подряд в stdout, то некоторые из этих раз выведутся некорректно (допустим, 7 раз искомая строка перезапишется, 3 раза выведется нормально)

ETERM *data = NULL;
data = erl_element(2, msg);
size = ERL_BIN_SIZE(data);
char *p = ERL_BIN_PTR(data);
for (i = 0; i < 10; i++)
{
    fprintf(stdout,"\nDEBUG progress_print() print output by fwrite ATTEMPT=%d\n",i+1);
    fwrite(p, 1, size, stdout);
    fwrite("\n", 1, 1, stdout);
}
Как видно из кода выше, p указывает на один и тот же кусок памяти, но почему-то выводится он по-разному. Проблема в терминале? В функции fwrite? Я уже голову сломал.

ignoramus8
() автор топика
Ответ на: комментарий от ignoramus8

В общем, всё выглядит так, как будто fwrite глючил из-за слишком длинного буфера (около 17КБ). Стал выводить буфер блоками по 1024 байта - проблема ушла. Вообще, LINE_SIZE в моей системе равен 2048, но конкретно на размере блока в 2048 проблема так же воспроизводилась.

ignoramus8
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.