Это меня поставило в тупик !
При использовании вызова async_read_until
может возникнуть проблема с распечаткой чего-либо более 4 Кбайт?
У меня есть маленькая функция, которая печатает 100 строк (чуть больше 4k).
Прекрасно работает в любой комбинации, кроме случаев регистрации обратного вызова async_read_until
. В этот момент мой вывод обрезается до 4k. Заметьте, что не всегда, хотя иногда меньше, а иногда и все это напечатано, похоже, что оно связано с нагрузкой на машину, почти как в случае тайм-аута? Какая-то нить Asio? В любом случае, если я закомментирую вызов async_read_until
, он работает каждый раз, независимо от того, сколько раз я звоню printLines
. Я даже могу использовать функцию ioService
post
, она отлично работает ...
Что происходит? Кстати, я использую Linux и AMD64 машины GCC4.4. (Redhat)
Используя linux ' strace ', я получил еще несколько подсказок:
Кажется, что после вызова async_read_until asio с использованием вызовов fcntl заставляет мой дескриптор выходного файла изменить поведение?
через некоторое время он прекращает печать:
выберите (4, [0 3], [], [], {300, 0}) = 1 (в [0], слева {298, 830000})
readv (0, [{"\ n \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 "..., 512}], 1) = 1
написать (2, «Это тест длинного предложения» ..., 93) = 93
написать (2, «Это тест длинного предложения» ..., 93) = 93
... около 40 раз
написать (2, «Это тест длинного предложения» ..., 93) = 53
write (2, "Это тест длинного предложения" ..., 93) = -1 EAGAIN (Ресурс временно недоступен)
write (2, "Это тест длинного предложения" ..., 93) = -1 EAGAIN (Ресурс временно недоступен)
write (2, "Это тест длинного предложения" ..., 93) = -1 EAGAIN (Ресурс временно недоступен)
write (2, "Это тест длинного предложения" ..., 93) = -1 EAGAIN (ресурс временно недоступен)
write (2, "Это тест длинного предложения" ..., 93) = -1 EAGAIN (Ресурс временно недоступен)
... для остальных, пока 100 не будет достигнуто.
Таким образом, вы можете увидеть цикл выбора, ожидающий мою клавишу ввода ввода. Тогда мы называем мой пустой
прочитайте обработчик и выйдите из ioService. В это время я вызываю свою функцию printLines и пытаюсь напечатать 100 строк, но она завершается после печати 40 некоторых.
Что-то с этим EAGAIN приводит к тому, что вывод прекращает запись.
Опять же, если я не вызову async_read_until, мой printf не будет поврежден.
Мне кажется, я знаю, что происходит , похоже, Asio переводит мой дескриптор файла stdout в асинхронный неблокирующий режим, когда я запрашиваю асинхронный режим чтения в дескрипторе файла stdin. Вот почему после некоторого вывода я получаю EAGAIN ошибки при записи. Конечно, printf игнорирует их, поэтому мой вывод усекается. Не знаете, это ошибка в Asio или просто побочный эффект в Linux?
Вот моя простая программа для дублирования проблемы:
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <iostream>
using namespace boost::asio;
using namespace std;
io_service ioService;
boost::asio::streambuf inStream;
posix::stream_descriptor input(ioService, STDIN_FILENO);
void printLines()
{
for (int i = 0; i < 100; i++) {
fprintf(stderr, "This is a test of a long sentence, there will be %d more sentences after this on is printed.\n", i);
}
fflush(stderr);
}
void readHandler(const boost::system::error_code& error)
{ // Don't care about read!! }
int main()
{
boost::system::error_code ec;
//printLines(); << this works if uncommented
//ioService.post(printLines); << this works if uncommented
boost::asio::async_read_until(input, inStream, "\n",
bind(readHandler, placeholders::error)); // causes truncated output
cout << "Hit Return to continue..." << endl;
ioService.run_one( ec );
assert(!ec);
printLines(); // partial output if async_read_until is called?
return 0;
}