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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QTcpSocket::readAll() SIGSEGV  (Прочитано 10809 раз)
RedDog
Гость
« : Сентябрь 02, 2015, 12:54 »

В TCP сервере сокет пускается в отдельном потоке:
Код:
void CSocketThread::run()
{
    client = QSharedPointer< QTcpSocket >( new QTcpSocket() );
    client->setSocketDescriptor( socketDescriptor );
    QObject::connect( client.data(), SIGNAL( readyRead() ),
                      this, SLOT( on_dataReceived() ), Qt::QueuedConnection );
    exec();
}

Код:
void CSocketThread::on_dataReceived()
{
    QTcpSocket* socket = qobject_cast< QTcpSocket* >( sender() );
    if( !socket )
    {
        return;
    }

    int bytesToRead = socket->bytesAvailable();

    QByteArray tmp = socket->read( bytesToRead );
......
......
......
}

Вот в самом сервере создается поток для сокета.
Код:
void CTcpServer::incomingConnection( qintptr handle )
{
    client = QSharedPointer< CSocketThread >( new CSocketThread( handle ) );
    QObject::connect( client.data(), &CSocketThread::dataReceived,
                      this, &CTcpServer::on_dataReceived );
    QObject::connect( client.data(), &QThread::finished,
                      client.data(), &QObject::deleteLater );
    client->start();
}

При чтении из сокета возникает SIGSEGV. Вылетает в случайном порядке. По объему данных никакой корреляции не увидел. Крайний раз bytesToRead = 608
ЧЯДНТ?
PS: Qt 5.3.0
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #1 : Сентябрь 02, 2015, 13:30 »

Цитировать
ЧЯДНТ?

Переменная QTcpSocket живет в потоке CSocketThread::run(), но bytesAvailable() и read() выполняются из главного.

ЗЫ: Ну сколько же раз будут еще такие темы подниматься? Самому проверить и подумать не судьба?
Записан

ArchLinux x86_64 / Win10 64 bit
RedDog
Гость
« Ответ #2 : Сентябрь 02, 2015, 13:40 »

Переменная QTcpSocket живет в потоке CSocketThread::run(), но bytesAvailable() и read() выполняются из главного.
Тогда встречный вопрос: как сделать что бы они в том же потоке выполнялись?
Записан
torwig
Самовар
**
Offline Offline

Сообщений: 134



Просмотр профиля
« Ответ #3 : Сентябрь 02, 2015, 14:04 »

В потоке, в котором создаете сокет, делаете все connect() и слоты там же пусть отрабатывают. Абсолютно всю работу с сокетом выносите в тот поток, где он был создан.
Записан
RedDog
Гость
« Ответ #4 : Сентябрь 02, 2015, 14:17 »

В потоке, в котором создаете сокет, делаете все connect() и слоты там же пусть отрабатывают. Абсолютно всю работу с сокетом выносите в тот поток, где он был создан.
Так у меня так все и сделано. В run() создаю сокет, там же делаю коннекты к слотам.
Записан
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #5 : Сентябрь 04, 2015, 12:07 »

ЧЯДНТ?

наследуешся от qthread ?

https://wiki.qt.io/Threads_Events_QObjects
Записан
Bepec
Гость
« Ответ #6 : Сентябрь 04, 2015, 14:13 »

qate поясните пожалуйста.

Возможно человек просто не знал, что при наследовании от QThread необходимо в конструктор добавлять moveToThread(this), дабы слоты и остальные ф-ции принадлежали потоку, а не оставались в потоке родителя.
Записан
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #7 : Сентябрь 04, 2015, 15:11 »

qate поясните пожалуйста.

я имел ввиду, что методика не наследоваться от qthread описано в http://doc.qt.io/qt-5/qthread.html

чем плох moveToThread(this) не могу сказать

Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #8 : Сентябрь 04, 2015, 15:58 »

чем плох moveToThread(this) не могу сказать

Код:
It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run(). 
This means that all of QThread's queued slots will execute in the old thread.
Thus, a developer who wishes to invoke slots in the new thread must use the worker-object approach;
new slots should not be implemented directly into a subclassed QThread.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #9 : Сентябрь 04, 2015, 16:00 »

чем плох moveToThread(this) не могу сказать

Код:
It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run(). 
This means that all of QThread's queued slots will execute in the old thread.
Thus, a developer who wishes to invoke slots in the new thread must use the worker-object approach;
new slots should not be implemented directly into a subclassed QThread.

Типа после moveToThread(this) у вас контрроллер треда (QThread) будет жить в треде, к-ый он контролирует и, по-хорошему, все его ф-ии (quit/wait) надо будет звать из этого потока. Типа если будете дергать из главного потока, то работать будет, но некошерно.
Записан
Bepec
Гость
« Ответ #10 : Сентябрь 04, 2015, 17:31 »

Столько копий было сломано, но в результате вывод - это равнозначные методы применения Улыбающийся
Записан
RedDog
Гость
« Ответ #11 : Сентябрь 07, 2015, 09:09 »

И все равно не понимаю...
Объект создал в потоке, подконнектил его там же.
Так почему слоты вызываются в другом потоке то?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Сентябрь 07, 2015, 09:50 »

И все равно не понимаю...
Объект создал в потоке, подконнектил его там же.
Так почему слоты вызываются в другом потоке то?
Потому что так работает Qt::AutoConnection
Записан
RedDog
Гость
« Ответ #13 : Сентябрь 07, 2015, 10:56 »

Потому что так работает Qt::AutoConnection
Однако, у меня Qt::QueuedConnection
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #14 : Сентябрь 07, 2015, 11:21 »

Цитировать
Qt::QueuedConnection

Все верно в этом случае - слот будет вызван из главного потока приложения. Можно попробовать задать DirectConnection (я не уверен что это правильный путь), но
тогда придется "защищать" прочитанные данные tmp, если планируется их передавать в основной поток:

Код
C++ (Qt)
...
int bytesToRead = socket->bytesAvailable();
QByteArray tmp = socket->read( bytesToRead );
...
 
// здесь надо что-то делать с tmp!
 
 
« Последнее редактирование: Сентябрь 07, 2015, 11:24 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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