LINUX.ORG.RU

Qt + posix threads, непредсказуемое поведение программы


1

1

Привет. Пишу простой мессенджер на c++/Qt, POSIX threads, POSIX sockets, платформа Linux Ubuntu 12.04. Вопрос... Можно ли передать указатель основного потока Qt программы в posix thread, вот листинг

#include <QApplication>
#include "MainWindow.hpp"
#include "pthread.h"
#include <signal.h>
#include <QEvent>
#include <QObject>
#include "MessageEvent.hpp"


//pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


void handler_sigsegv(int signum)
{
    QMessageBox m_msg;
    m_msg.warning(0,"Warning", "SIGSEGV Error!","POSIX Signal");

    signal(signum, SIG_DFL);
    exit(3);
}

void* users(void* pt)
{    
  MainWindow* temp = (MainWindow*)pt;// переданный потоку параметр-указатель класса главного окна

   while(1)
   {
            if(1 == temp->get_login_status())// проверяем залогинился ли юзер
            { 
                QString string = temp->_receving();// ждем и получаем входящее сообщение
                if(NULL != string)
                {
                    // функция temp->getHistoryObj() возвращает указатель на QTextEdit
                    QMetaObject::invokeMethod(temp->getHistoryObj(), "insertPlainText"  ,Q_ARG(QString, string));// выводим в QTextEdit
                    QMetaObject::invokeMethod(temp->getHistoryObj(), "insertPlainText",Q_ARG(QString, "\n"));                   
                }                
            }
   }

}
int main(int argc, char** argv)
{
    signal(SIGPIPE, SIG_IGN);// сигнал sigpipe
    QApplication app(argc, argv);
    signal(SIGSEGV, handler_sigsegv);
    MainWindow* m = new MainWindow; //указатель на класс главного окна

    pthread_t pt;
    m->show();
    int res = pthread_create(&pt, NULL, &users, (void*)m); // создаем поток для получения входящих сообщений

    return app.exec();
}
Проблема в том что, что иногда прогрмма ведет себя непредсказуемо, не часто но бывает что сервер отправляет сообщение а тут клиент падает хотя минуты назад тот же клиент сообщение норм получало....Debuger -ом проверяю оказывается функция сокета recv возвращает -1, хотя минуты назад снова было все норм recv возвращала valid count байтов. тут у меня указатель класса главного окна MainWindow* m передается в posix поток. В потоке жду входящего сообщения. Если сообщение пришло то функция _receving() возвращает входящее сообщение ввиде строки QString. А методами QMetaObject::invokeMethod строка выводится в QTextEdit. Может не так-уж корректна передача указателя главного потока (main) Qt класса в posix поток void* users(void* pt) ?



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

Ответ на: комментарий от Yareg

neutrino 1 1 Qt + posix threads, непредсказуемое поведение программы

я этот проект делаю в рамках Internship программы и там условие что надо пользоватся posix thread- ами

neutrino
() автор топика

Вообще говоря, методы ui-класса можно вызывать только из одной нити, где он был создан.

vzzo ★★★
()

проверяю оказывается функция сокета recv возвращает -1

И какая ошибка в errno? EINTR?

Заметь, ты не приводишь кода MainWindow::_receving(), и поэтому твой вопрос сводится только к «Может не так-уж корректна передача указателя...», на который можно ответить просто - может.

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

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

я тебе открою секрет)

Для меня ничего не является секретом.

А я всего лишь констатировал один отдельный факт. Если ТСу не критично использование pthreads напрямую, то вполне можно использовать QThread — всё равно pthreads будут использованы, как ему и нужно.

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

Итак, открыл

nc -listen -p 8888
Твоя прога пишет туда (если ввести имя a):
securea
Я ввожу какой-нить ответ, твоя прога его отображает и... закрывает соединение, но по-прежнему предлагает «logout». Короче, чинить там слишком много нужно, начиная с логики. А уже потом вместо
err = _recv() / err = _send()
assert(err != -1);
написать нормальное
err = _recv() / err = _send()
if (err == -1) {
   // perror(); // для себя
   // ... обработать ошибку как полагается
}

А логика в кратце: не нужно закрывать только что установленное соединение m_clnt[0] и пытаться открывать новое m_clnt[1]! Могу только посоветовать посмотреть примеры простейших клиент/сервера в инете.

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

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

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

Вктчратце логика проги такая... узер ввел логин и вошел, сокет по порту 8888 закрывается. Этот порт нужен только для логина. Потом уже для мессиджинга создаются два сокета по 9000 и 8000 портам, соответственно для recv и send а. A для logout-a можно потом снова открыть 8000 порт и делать выйти а можно и совсем не закрывать...

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

а это корректно так взять и передать указатель класса главного окна второму потоку...

Вполне, если не делать с ним ничего плохого типа вызова его методов безо всякой синхронизации в твоем исходнике. Для invokeMethod передавай другой указатель непосредственно на тот объект, с которым работаешь, сделай в другом потоке Qtшный event loop.

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