Модераторы: feodorv

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> баг asio? или баг TCP стека? 
V
    Опции темы
boostcoder
Дата 23.3.2011, 14:30 (ссылка)    | (голосов:4) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



всем доброго дня.

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

код клиента выполняет следующее:
1. выделение памяти у ОС в boost::shared_array.
2. сериализация.
3. копирование в shared_array.
4. boost::asio::async_write().
5. tcpdump показывает что данные ушли.
6. на приеме данные искажены.

лог tcpdump`a для пояснения формирования непонятных "фреймов":
строки сериализации содержащие подстроки servimpl - это то, что отправляется от клиента серверу.
строки сериализации содержащие подстроки type1 - это то, что отправляется от сервера клиенту.
user posted image
что за непонятные данные присутствующие кроме архивов сериализации - мне не известно.
в точке 1 показан пример когда архив разбивается. в точке 2 показана остальная часть архива. этот архив на принимающей стороне восстанавливается правильно. ошибки не возникает.

далее...
в точке 3 происходит разбиение очередного архива, остальная часть которого появляется только в точке 5.
т.е. это именно та итерация(348), на которой происходит искажение архива, и как следствие - ошибка десериализации.
user posted image

далее...
в точке 4 должен находится остаток архива разбитого в точке 3.
user posted image

вот та часть, в которой появляется остаток от архива разбитого в точке 3.
user posted image

какие мысли?

Это сообщение отредактировал(а) boostcoder - 8.4.2011, 00:57
PM WWW   Вверх
Daevaorn
Дата 23.3.2011, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: нет
Всего: 70



Где код?
PM MAIL WWW   Вверх
boostcoder
Дата 23.3.2011, 15:13 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Daevaorn, не нужен вам код. в коде все ок. архивы отправляются целые.
причину нужно искать в том коде, который добавляет к моим данным нечитаемые данные и разбивает мои данные на "фреймы".

Добавлено через 1 минуту и 35 секунд
я рассчитывал на то, что кто-то увидит знакомую ситуацию, и подскажет как решить.

зы
кстати, если между отправками данных поставить sleep на 1мс - то проблема решается полностью.
PM WWW   Вверх
boostcoder
Дата 23.3.2011, 15:58 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(boostcoder @  23.3.2011,  15:13 Найти цитируемый пост)
причину нужно искать в том коде, который добавляет к моим данным нечитаемые данные и разбивает мои данные на "фреймы".

кто-то знает кто может добавлять к моим данным нечитаемые данные и разбивать их на фреймы? это выполняет TCP стек? сетевая подсистема? просто не знаю как это называется...

Это сообщение отредактировал(а) boostcoder - 23.3.2011, 16:07
PM WWW   Вверх
boostcoder
Дата 24.3.2011, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



прикладываю мегапростой пример воспроизводящий ошибку.


Присоединённый файл ( Кол-во скачиваний: 11 )
Присоединённый файл  asiotest.zip 2,75 Kb
PM WWW   Вверх
MAKCim
Дата 27.3.2011, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



Цитата(boostcoder @  23.3.2011,  15:58 Найти цитируемый пост)
это выполняет TCP стек?

фрагментация осуществляется на сетевом уровне
к данным "мусор" добавляться не может

вы точно уверены, что в сокет все записывается правильно?
вы сравнивали, что передается в async_write() и в send()?


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
marykone
Дата 27.3.2011, 21:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2722
Регистрация: 2.5.2006
Где: Краснодар

Репутация: нет
Всего: 67



boostcoder, данные скорее всего искажены именно от отправителя.
На первый взгляд, именно так. копать... 
Если дальше копать то послушайте трафик wireshark, и выложите сюда. ну может конечно кто то и tcp дамп почитать смоежт я как то не.



--------------------
получил ответ, пометь вопрос как решенный (правый верхний угол вашей темы).

PM   Вверх
MAKCim
Дата 27.3.2011, 21:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



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


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
boostcoder
Дата 28.3.2011, 15:18 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(MAKCim @  27.3.2011,  21:06 Найти цитируемый пост)
фрагментация осуществляется на сетевом уровне
к данным "мусор" добавляться не может

тот мусор что на скринах, показывает tcpdump. в мой код этот мусор не поступает.

Цитата(MAKCim @  27.3.2011,  21:06 Найти цитируемый пост)
вы точно уверены, что в сокет все записывается правильно?

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

Цитата(MAKCim @  27.3.2011,  21:06 Найти цитируемый пост)
вы сравнивали, что передается в async_write() и в send()? 

нет. а как это сделать? добавить в недры asio вывод?
или есть какой-то еще способ?

Цитата(marykone @  27.3.2011,  21:17 Найти цитируемый пост)
послушайте трафик wireshark, и выложите сюда.

сейчас сделаю.

Цитата(MAKCim @  27.3.2011,  21:43 Найти цитируемый пост)
если постоянно записывать данные, а читать с задержкой 1 мс, то данные будут накапливаться в буфере сокета ядра...хм, может тут проблема

эм.. помогает задержка при записи, а не при чтении.

Цитата(MAKCim @  27.3.2011,  21:43 Найти цитируемый пост)
версия ядра какая?

я проверял не только на линукс...

клиентский код запускаю на: 2.6.35-28-generic-pae
код сервера на: 2.6.35-25-generic-pae
PM WWW   Вверх
boostcoder
Дата 28.3.2011, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



логи.
сделал wireshark`ом на локальной стороне.
на сервере нет X`ов, я хз как там wireshark запускать.

зы
по логам, ничего не понял...


Присоединённый файл ( Кол-во скачиваний: 5 )
Присоединённый файл  logs.zip 76,38 Kb
PM WWW   Вверх
boostcoder
Дата 28.3.2011, 18:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



заново протестил еще раз на winXP/Win7/Linux.
баг воспроизводится всегда :(
тестил так:
Цитата

клиент | сервер | локально/удаленно
-------------------------------------
WinXP    WinXP    локально
WinXP    Linux    удаленно
Win7     Win7     локально
Win7     Linux    удаленно
Linux    Linux    локально
Linux    Linux    удаленно

PM WWW   Вверх
MAKCim
Дата 29.3.2011, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



Цитата(boostcoder @  28.3.2011,  15:18 Найти цитируемый пост)
насколько это возможно утверждать на приведенном коде - да. просто код реально мегапрост, чтоб где-то мог закрасться баг. если конечно это не баг asio. в чем сомневаюсь.. 

в этом большая ошибка
я много раз на это же полагался
а в итоге как раз в мегапростом коде и был баг ;)


Цитата(boostcoder @  28.3.2011,  15:18 Найти цитируемый пост)
нет. а как это сделать? добавить в недры asio вывод?
или есть какой-то еще способ?

написать враперы над send/recv/... из Libc
насколько я знаю, достаточно создать что-то типа wrappers.c, там реализовать обертки
вот реальный код подмены fork из какого-то проекта...
Код

#ifndef NO_PROCESS_LOCK
static pid_t (*_fork)();

HOOK_FUNCTION pid_t fork()
{
    pid_t pid;
#ifdef DEBUG
    fprintf(stdout, "fork()\n");
#endif
    start_fork();
    pid = _fork();
    if (pid == 0)
    {
    }
    else if (pid > 0)
    {
        end_fork();
    }
    return pid;
}
#endif

int PLogInit()
{
#ifndef NO_PROCESS_LOCK
    void *ptr;
    if ((ptr = dlsym(RTLD_NEXT, "fork")) == NULL)
    {
        fprintf(stderr, "dlsym() failed\n");
        return -1;
    }
    _fork = ptr;
#endif
    return 0;
}


Добавлено через 3 минуты и 2 секунды
Цитата(boostcoder @  28.3.2011,  18:49 Найти цитируемый пост)
баг воспроизводится всегда :(

в таком случае я уверен на 99% баг где-то в коде
думаю в вашем, а не asio


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
phprus
Дата 2.4.2011, 22:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 22.8.2006

Репутация: 1
Всего: 3



Почитал я код и у меня возникло подозрение, что async_test() и asio в клиенте работают в разных потоках. А shared_array (как и shared_ptr) не может корректно передаваться между потоками (по крайней мере я пару месяцев назад не нашел такого способа).
Те когда выполняется код:
Код

boost::shared_array<char> buf(new char[send_buffer_size]);
sprintf(buf.get(), "cs:%8d\n", idx);
start_write(_sock, buf); // <----
if ( _ws ) {
     boost::this_thread::sleep(boost::posix_time::microseconds(1000));
}
 // <----

в отмеченных местах возникает состояние гонки, а так-же в функции start_write в вызове boost::bind происходят изменения в счетчике ссылок shared_array и последний ломается. Если не повезет один из деструкторов shared_array может убить данные раньше чем обновятся данные счетчика ссылок.

В свое время пару месяцев назад я напоролся на точно такой-же баг, но только с shared_ptr, через который между потоками передавался вектор. Весь процесс передачи был обернут мутексами, кроме участков, где возможно удаление временных объектов shared_ptr (а они возникали так как данные передавались через std::queue), но программа всеравно падала где-то в недрах asio. А иногда не падала, а что-то передавала.
И что самое паршивое в GCC все работало. А в Intel C++ падало или не падало. Зависело это от фазы луны, загрузки процессора и т. д.

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

Потокобезопасность shared_ptr описана здесь: http://www.boost.org/doc/libs/1_46_1/libs/...tm#ThreadSafety (Example 3 описывает возникшую ситуацию).
PM MAIL WWW ICQ   Вверх
boostcoder
Дата 2.4.2011, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



перевариваю...

Добавлено через 41 секунду
а по этой проблеме, которая у вас возникла, вы где-то на форуме тему создавали? хотелось бы почитать.
PM WWW   Вверх
phprus
Дата 2.4.2011, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 22.8.2006

Репутация: 1
Всего: 3



Нет, не создавал. Что-бы создать тему нужна была хоть какая-либо детализация проблемы, а у меня даже segmentation fault в разных местах всплывали. Я неделю думал, что на какой-то хитрый баг либо в asio либо в intel С++ наткнулся. Потом начал искать все места, который потенциально перераспределяли память и где рядом был обмен данными между потоками. С 3-й попытки заменил нужный shared_ptr на обычный ptr и ручное управление памятью и проблема ушла полностью.
PM MAIL WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.1024 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.