Problem(deadlock) mit Threads und Qt
-
Hi, ich wollt mich in Multithreading reinarbeiten, indem ich mir einen Netzwerk thread baue, doch irgendwie bekomm ich nach ner zeit nur nen deadlock
qteamspeakthread.cpp
#include "qteamspeakthread.h" #include <QMutexLocker> #include <QTextStream> #include <iostream> #include <QMessageBox> using namespace std; QTeamspeakThread::QTeamspeakThread() : QThread() { state = 0; quit = false; } void QTeamspeakThread::refresh() { QMutexLocker locker(&mutex); if(!isRunning()) { start(); } else { cond.wakeOne(); } } void QTeamspeakThread::connectToServer(const QString &ip,const QString &port,quint16 qport) { QMutexLocker locker(&mutex); this->hostname = ip; this->port = port; this->qport = qport; state |= 1; if(!isRunning()) { start(); } else { cond.wakeOne(); } } void QTeamspeakThread::sendRequest(const QString &request) { QMutexLocker locker(&mutex); state |= 2; query = request; if(!isRunning()) { start(); } else { cond.wakeOne(); } } void QTeamspeakThread::disconnectFromServer() { QMutexLocker locker(&mutex); state |= 4; if(!isRunning()) { start(); } else { cond.wakeOne(); } } void QTeamspeakThread::run() { QMutexLocker locker(&mutex); QTcpSocket socket; QString ServerName = hostname; quint16 ServerPort = qport; int state = this->state; while(!quit) { if(state & 1) { socket.connectToHost(ServerName,ServerPort); if(!socket.waitForConnected()) { emit error(socket.error(),socket.errorString()); return; } while(socket.bytesAvailable() < (int)sizeof(quint8)) { if(!socket.waitForReadyRead()) { emit error(socket.error(),socket.errorString()); return; } } qDebug(socket.readLine()); state |= 1; } QTextStream *t = new QTextStream(&socket); if(state & 2) { *t<<query<<"\r\n"; t->flush(); while(socket.bytesAvailable() < (int)sizeof(quint8)) { if(!socket.waitForReadyRead()) { emit error(socket.error(),socket.errorString()); return; } } qDebug(socket.readLine()); state |= 2; } if(state & 4) { socket.disconnectFromHost(); state |= 4; qDebug("disconnected"); } cond.wait(&mutex); /* *t<<query<<"\r\n"; t->flush();*/ } } QTeamspeakThread::~QTeamspeakThread() { quit = true; cond.wakeOne(); wait(); }
qteamspeakthread.h
#ifndef QTEAMSPEAKTHREAD_H #define QTEAMSPEAKTHREAD_H #include <QThread> #include <QMutex> #include <QWaitCondition> #include <QTcpSocket> class QTeamspeakThread : public QThread { Q_OBJECT public: QTeamspeakThread(); ~QTeamspeakThread(); protected: void run(); private: QString hostname; QString port; QString query; quint16 qport; QMutex mutex; QWaitCondition cond; bool quit; volatile int state; public slots: void connectToServer(const QString &ip,const QString &port,quint16 qport); void refresh(); void sendRequest(const QString &request); void disconnectFromServer(); signals: void error(int socketError,const QString &message); }; #endif
Schonmal danke für die hilfe
-
Wo hängt es denn? Füge mal die Tracebacks der einzelnen Threads hinzu.
Das volatile für state ist überflüssig und bringt nichts.
Kannst du mal ein vollständiges simples Programm erstellen, so dass man den Fehler selbst sieht?
-
Wie kann ich einen Traceback von den Threads machen? es stehen mir alle Linux spezifischen tools bereit
-
Deadlocker der Nation schrieb:
Wie kann ich einen Traceback von den Threads machen? es stehen mir alle Linux spezifischen tools bereit
Mit dem gdb. "info threads" für alle Threads. Dann "thread <num>", um einen Thread anzuspringen. Die Nummern gibt "info threads". Dann "where" für den Traceback.
-
hier ist der Traceback:
#0 0xffffe410 in __kernel_vsyscall () #1 0xb76a85c6 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/tls/i686/cmov/libpthread.so.0 #2 0xb76f37ef in ?? () from /usr/lib/libQtCore.so.4 #3 0xb76f0b2d in QMutex::lock () from /usr/lib/libQtCore.so.4 #4 0x0804d5a0 in QTeamspeakThread::disconnectFromServer () #5 0x0804e465 in QTeamspeakThread::qt_metacall () #6 0xb77abaa8 in QMetaObject::activate () from /usr/lib/libQtCore.so.4 #7 0xb77abd2f in QMetaObject::activate () from /usr/lib/libQtCore.so.4 #8 0xb7996831 in QAction::triggered () from /usr/lib/libQtGui.so.4 #9 0xb79971bf in QAction::activate () from /usr/lib/libQtGui.so.4 #10 0xb7c9dfd4 in ?? () from /usr/lib/libQtGui.so.4 #11 0xb7ca0726 in QMenu::mouseReleaseEvent () from /usr/lib/libQtGui.so.4 #12 0xb79e7e41 in QWidget::event () from /usr/lib/libQtGui.so.4 #13 0xb7c9b31c in QMenu::event () from /usr/lib/libQtGui.so.4 #14 0xb799d190 in QApplicationPrivate::notify_helper () from /usr/lib/libQtGui.so.4 #15 0xb799fbf3 in QApplication::notify () from /usr/lib/libQtGui.so.4 #16 0xb79f90a7 in ?? () from /usr/lib/libQtGui.so.4 #17 0xb79f71c8 in QApplication::x11ProcessEvent () from /usr/lib/libQtGui.so.4 #18 0xb7a1bf34 in ?? () from /usr/lib/libQtGui.so.4 #19 0xb730adf2 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0 #20 0xb730ddcf in ?? () from /usr/lib/libglib-2.0.so.0 #21 0x0805dc90 in ?? () #22 0x00000000 in ?? ()
Die State Variable will sich in dem Thread auch nicht ändern, wenn ich einmal connecte, und dann disconnecten will, dann führt mein programm die anweisung fürs connecten aus und nich die fürs disconnecten. Wenn ich dreimal connecten oder disconnecten betätige, dann hab ich den deadlock.
-
sory, falscher Thread gewesen, hier ist der richtige.
thread traceback
#0 0xffffe410 in __kernel_vsyscall () #1 0xb76a85c6 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib/tls/i686/cmov/libpthread.so.0 #2 0xb76f37ef in ?? () from /usr/lib/libQtCore.so.4 #3 0xb76f0b2d in QMutex::lock () from /usr/lib/libQtCore.so.4 #4 0xb76f4c72 in QWaitCondition::wait () from /usr/lib/libQtCore.so.4 #5 0x0804dd51 in QTeamspeakThread::run () #6 0xb76f4262 in ?? () from /usr/lib/libQtCore.so.4 #7 0xb76a431b in start_thread () from /lib/tls/i686/cmov/libpthread.so.0 #8 0xb751057e in clone () from /lib/tls/i686/cmov/libc.so.6
-
Wenn du nicht siehst, was falsch ist, werden wir das so auch kaum sehen. Da hilft eigentlich nur ein Lauffähiges minimalprogramm, das auch den Fehler hat.
-
Ich hab mal ein minimalprog geschrieben
main.cpp
#include <QCoreApplication> #include "mainthread.h" #include "thread.h" #include <iostream> using namespace std; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); mainThread mt; Thread t; QObject::connect(&mt,SIGNAL(connectTo()),&t,SLOT(connectToServer())); QObject::connect(&mt,SIGNAL(disconnectFrom()),&t,SLOT(disconnectFromServer())); QObject::connect(&mt,SIGNAL(sendReq()),&t,SLOT(sendRequest())); while(1) { mt.getInput(); } return 0; }
mainthread.h
#ifndef MAINTHREAD_H #define MAINTHREAD_H #include<QObject> class mainThread : public QObject { Q_OBJECT public: mainThread(); void getInput(); ~mainThread(); signals: void connectTo(); void sendReq(); void disconnectFrom(); }; #endif
mainthread.cpp
#include "mainthread.h" #include<iostream> using namespace std; mainThread::mainThread() { } void mainThread::getInput() { int s = 0; cout<<"1: connect\n2: disconnect\n3: send request"<<endl; cin>>s; if(s == 1) { emit connectTo(); } else if(s == 2) { emit disconnectFrom(); } else if(s == 3) { emit sendReq(); } } mainThread::~mainThread() { }
thread.h
#ifndef QTEAMSPEAKTHREAD_H #define QTEAMSPEAKTHREAD_H #include <QThread> #include <QMutex> #include <QWaitCondition> class Thread : public QThread { Q_OBJECT public: Thread(); ~Thread(); protected: void run(); private: QMutex mutex; QWaitCondition cond; bool quit; volatile int state; public slots: void connectToServer(); void refresh(); void sendRequest(); void disconnectFromServer(); signals: void error(int socketError,const QString &message); };
thread.cpp
#include "thread.h" #include <QMutexLocker> #include <QTextStream> #include <iostream> using namespace std; Thread::Thread() : QThread() { state = 0; quit = false; } void Thread::refresh() { QMutexLocker locker(&mutex); if(!isRunning()) { start(); } else { cond.wakeOne(); } } void Thread::connectToServer() { QMutexLocker locker(&mutex); state |= 1; if(!isRunning()) { start(); } else { cond.wakeOne(); } } void Thread::sendRequest() { QMutexLocker locker(&mutex); state |= 2; if(!isRunning()) { start(); } else { cond.wakeOne(); } } void Thread::disconnectFromServer() { QMutexLocker locker(&mutex); state |= 4; if(!isRunning()) { start(); } else { cond.wakeOne(); } } void Thread::run() { while(!quit) { if(state & 1) { cout<<"State 1"<<endl; state |= 1; } if(state & 2) { cout<<"State 2"<<endl; state |=2; } if(state & 4) { cout<<"state 3"<<endl; state |=4; } cond.wait(&mutex); } } Thread::~Thread() { quit = true; cond.wakeOne(); wait(); }
-
Ich habe mir jetzt dein Programm angeschaut und kann da keine sinnvolle Struktur erkennen, und sehe keinen Ansatzpunkt, um das zu korrigieren.
Kannst du mal aufschreiben, welche Aufgaben deine Threads haben, und was sie machen sollen? Mach mal ein Ablaufdiagramm, das zeigt, wie die Schritte, die du dir vorstellst zeitlich ausgeführt werden.
-
das Problem ist schon gelöst