Russian Qt Forum
Ноябрь 23, 2024, 00:49 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Некорректное поведение многопоточной программы  (Прочитано 9895 раз)
xaleva
Гость
« : Февраль 15, 2011, 12:59 »

Добрый день.Кто нибудь сталкивался с такой проблемой: многпоточное сокетное приложение,временами начинает некорректно работать.Сообщения получает не правильно(обрезает,причем не из за того что превышается длина,а просто вместо 2 символов получает один),а иногда зацикливается(это можно увидеть по логированию).Вопрос,могут ли не правильно используемые мьютексы привести к такому?При этом циклы не используются естественно.
« Последнее редактирование: Февраль 15, 2011, 13:03 от xaleva » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Февраль 15, 2011, 20:07 »

Вопрос,могут ли не правильно используемые мьютексы привести к такому?При этом циклы не используются естественно.
Конечно могут, но это также может быть все что угодно - пока по Вашему общему описанию ничего конкретного сказать нельзя.
Записан
xaleva
Гость
« Ответ #2 : Февраль 15, 2011, 20:32 »

Ок, тогда приведу общую картину.В главном потоке создаются потоки:

  TerminalThread *_thread = new TerminalThread (*_terminalList[number]);
    connect (_thread,SIGNAL (signalSocketConnected (QString)),this,SLOT (slotSocketConnected (QString)),Qt::QueuedConnection);
 и т.д....

в TerminalThread::run следующий код:
void TerminalThread::run ()
{
    Terminal _terminal (_terminalObject);
    _terminal.moveToThread (this);
    connect (&_terminal,SIGNAL (signalSocketConnected (QString)),this,SLOT (slotSocketConnected (QString)),Qt::QueuedConnection);
   ...и т.д

    _terminal.tryConnection ();
    exec ();
    disconnect (&_terminal,SIGNAL (signalSocketConnected (QString)),this,SLOT (slotSocketConnected (QString)));
... и т.д
}


Terminal.cpp:

Terminal::Terminal (TerminalObject& terminal)
{
    _socket = new QTcpSocket (this);
    _timer = new QTimer (this);
    connect (_timer,SIGNAL (timeout ()),this,SLOT (slotConnectionTimer ()));
    ...
}

void Terminal::slotSocketReadyRead ()
{
    QTextStream stream (_socket);
    QString value = stream.readAll ();
    checkSignal (value);
}

void Terminal::checkSignal (QString value)
{
      .....
    _log.writeLog (val);
}

Вот здесь переменная _log это singletone.Внутри синглтона и внутри TerminalObject все функции начинаются с записи QMutexLocker locker (&_mutex);
Т.е в принципе,все сигналы типа QueuedConnection, значит блокирование должно происходить только после завершения eventLoop, т.е блокирование не происходит.Все синглтоны вроде обезопасены записью QMutexLocker locker (&_mutex);
Есть ли ошибки в проектировании или я правильно все синхронизировал.
Записан
xaleva
Гость
« Ответ #3 : Февраль 16, 2011, 09:53 »

    QTextStream stream (_socket);
    QString value = stream.readAll ();

Такой еще вопрос: readAll работает всегда правильно?
Записан
BRE
Гость
« Ответ #4 : Февраль 16, 2011, 10:05 »

readAll работает всегда правильно?
Ну в общем то да.  Улыбающийся
Эта конструкция вычитывает из сокета все, что пришло на текущий момент.
Записан
kdm
Гость
« Ответ #5 : Февраль 16, 2011, 10:10 »

В примерах к какой-то книги есть такой момент, что в пакет сообщения в начало вставляется длина пакета в байтах (sizeof). В клиенте действительно принимается все что пришло именно на текущий момент и производится проверка пришел ли весь пакет, если нет то "обрабатывающий" класс ждет дальше. Просто в памяти вспомнился такой момент, не мог понять почему так и нет автоматических средств для таких случаев. Книгу сейчас не помню, но если что посмотрю, где-то валяется с примерами.
(ЗЫ может где-то в терминах неправильно выразился)
Записан
xaleva
Гость
« Ответ #6 : Февраль 16, 2011, 10:14 »

Тогда ничего не понятно  Улыбающийся Никак не могу найти,в чем проблема.При тестировании ничего не вылезает.Но в реальных условиях,при 5-6 подключениях вдруг творится чтот не понятное.Ок, тогда:
1. То,что сигналы от главного потока и обратно соединены типом QueuedConnection может как то повлиять?
2. То,что я в главном создаю синглтоны для работы с логированием и базой данных а потом в дочерних беру их instance и использую,причем все методы внутри синглтона защищены QMutexLocker _locker (&_mutex);, может как то повлиять?


Записан
xaleva
Гость
« Ответ #7 : Февраль 16, 2011, 10:16 »

Да, это используется,если я побайтово принимаю сообщение.Я не стал это делать,потому что у меня все сообщения текстовые, 2 символа и конец строки.Иногда они склеиваются почему то,но все равно есть возможность split ом разделить по \t или \n
Записан
BRE
Гость
« Ответ #8 : Февраль 16, 2011, 10:19 »

не мог понять почему так и нет автоматических средств для таких случаев.
Наверное потому, что это только один из вариантов контроля потока с данными. Есть и другие, для примера можно вспомнить такие протоколы как http, ftp.
Записан
BRE
Гость
« Ответ #9 : Февраль 16, 2011, 10:33 »

После всего написанного, тебя не смущает твой слот?  Подмигивающий
Код
C++ (Qt)
void Terminal::slotSocketReadyRead ()
{
   QTextStream stream (_socket);
   QString value = stream.readAll ();
   checkSignal (value);
}
 

Что будет, если этот слот вызовется когда придет только половина сообщения или полтора сообщения?
Записан
xaleva
Гость
« Ответ #10 : Февраль 16, 2011, 10:40 »

 Улыбающийся а что будет если придет половина сообщения? Он считает половину, запишет,потом через некоторое время придет другая половина.Проблема в том что пол логам выходит что из двух символов сообщения приходит второй,а первый вообще никак не отмечается в логах,поэтому момент,что сообщение обрезается на две части я отбросил
Записан
kdm
Гость
« Ответ #11 : Февраль 16, 2011, 10:42 »

Улыбающийся а что будет если придет половина сообщения? Он считает половину, запишет,потом через некоторое время придет другая половина.Проблема в том что пол логам выходит что из двух символов сообщения приходит второй,а первый вообще никак не отмечается в логах,поэтому момент,что сообщение обрезается на две части я отбросил
Может лучше обратится к стандартным примерам. Тем более если только текстовые сообщения?
Выложил бы для интереса других людей проект в сообщении (если не корпоративная тайна))), а то не пойму зачем таймеры, мутексы...
Пример что я видел достаточно прост и без этих хитростей.
« Последнее редактирование: Февраль 16, 2011, 10:48 от kdm » Записан
BRE
Гость
« Ответ #12 : Февраль 16, 2011, 10:49 »

,поэтому момент,что сообщение обрезается на две части я отбросил
Ну и напрасно. Стек tcp гарантирует целостность всех передаваемых данных, т.е. он не может "глотать" какие-то данные и молча отдавать тебе следующие.  Улыбающийся

Единственное объяснение, это первый символ сообщения просто "прилипает" к предыдущему сообщению.
Записан
xaleva
Гость
« Ответ #13 : Февраль 16, 2011, 10:55 »

Да, а предыдущее тоже ведь записывается с лог, я бы заметил это.Да,и еще забыл уточнить, сообщения обычно идут максимум 1 в сек.А во время сбоя в секунду по 10 раз этот один символ...как будто зацикливается..
Записан
BRE
Гость
« Ответ #14 : Февраль 16, 2011, 11:42 »

Да, а предыдущее тоже ведь записывается с лог, я бы заметил это.Да,и еще забыл уточнить, сообщения обычно идут максимум 1 в сек.А во время сбоя в секунду по 10 раз этот один символ...как будто зацикливается..
Ну тут сложно что-то сказать, что там где зацикливается, попробуй вставить отладочный ввод в сам слот приема и посмотри что он читает:
Код
C++ (Qt)
void Terminal::slotSocketReadyRead ()
{
QByteArray data = _socket.readAll();
qDebug() << data.toHex();
checkSignal( data );
}
 
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.179 секунд. Запросов: 23.