SIGSEGV bei TCP Socket

Alles rund um die Programmierung mit Qt
Antworten
Ozzy
Beiträge: 141
Registriert: 24. Oktober 2007 10:18

SIGSEGV bei TCP Socket

Beitrag von Ozzy »

Hi,

ich arbeite gerade an einer kleinen Qt-App für Android, wo Daten über W-LAN von einem anderen Gerät empfangen werden sollen. Diese Daten werden dann zyklich (alle 50ms) von einem Programmteil "abgeholt". Hierfür habe ich eine Socket-Klasse geschrieben:

Code: Alles auswählen

TCPSocket::TCPSocket(QObject *parent) :
    QObject(parent)
{
    reconnectTimer = new QTimer(this);
    m_tcpSocket = new QTcpSocket(this);
    connect(this, SIGNAL(startTimer()), this, SLOT(startTimerSlot()));
    connect(this, SIGNAL(stopTimer()), this, SLOT(stopTimerSlot()));

    connect(reconnectTimer, SIGNAL(timeout()), this, SLOT(reconnectTimerSlot()));
    reconnectTimer->setInterval(5000);

    connectServer();
}

void TCPSocket::connectServer()
{

    if (!reconnectTimer->isActive())
    {
        emit startTimer();
    }
    m_tcpSocket->abort();
    m_tcpSocket->connectToHost(IP, PORT);
    connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(readMesg()));
    connect(m_tcpSocket, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
    connect(m_tcpSocket, SIGNAL(connected()), this, SLOT(onConnected()));
}


Falls die Verbindung getrennt wird, wird so alle 5 Sekunden probiert, sie wieder herzustellen. Wenn das "connected"-Signal kommt, wird der Timer wieder ausgeschaltet:

Code: Alles auswählen

void TCPSocket::onConnected()
{
#ifdef DEBUG
    qDebug() << QTime::currentTime().toString() << "TCPSocket: Connected... ";
#endif
    bIsConnected = true;
    emit stopTimer();
}
Hier werden die Daten (über Umwege) vom Socket in eine Queue gelesen:

Code: Alles auswählen

void TCPSocket::readMesg() //read msg
{
    if(bIsConnected)
    {
        try
        {
            qDebug() << "Read: " << m_tcpSocket->bytesAvailable();
            QByteArray qba = m_tcpSocket->readAll();

            for (int i=0; i<qba.length(); i++)
            {
                queue.enqueue(qba[i]);
            }
        }
        catch (std::exception &e)
        {
            qDebug() << "Exception: " << e.what();
        }
    }
}
und so später vom Prozess wieder ausgelesen:

Code: Alles auswählen

int TCPSocket::receiveData( U_BYTE_8 *receivedData )
{
    int i=0;

    qDebug() << queue.size();
    while (!queue.isEmpty())
    {
        receivedData[i] = queue.dequeue();
        i++;
    }
    qDebug() << "finished.";
    return i;
}
Das ganze geht auch einige Zeit gut, dann kommt es aber zum Segmentation fault. Der tritt auch nicht immer an der gleichen Stelle auf, sondern mal hier:

Code: Alles auswählen

qDebug() << "Read: " << m_tcpSocket->bytesAvailable();
oder hier

Code: Alles auswählen

QByteArray qba = m_tcpSocket->readAll();
oder hier

Code: Alles auswählen

m_tcpSocket->write(buffer);
Mir ist allerdings (mangels fehlender Erfahrung) nicht klar, warum er manchmal nicht auf den TCP Socket zugreifen kann. Was ich im Debugger sehe, ist, dass häufig kleine Pakete ankommen (<100 Bytes), sich dann die Schnittstelle wohl verschluckt (WLan-Signal ist nicht besonders gut), und dann plötzlich gerne mal mehr als 2000 bytes kommen.

Habt Ihr da einen Tip für mich? Muss ich das noch irgendwie mit Semaphoren schützen? Oder weitere Abfragen machen??? Bin da langsam echt ratlos...

Vielen Dank im Voraus,
Ozzy
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: SIGSEGV bei TCP Socket

Beitrag von RHBaum »

int TCPSocket::receiveData( U_BYTE_8 *receivedData )
wie gross ist receivedData und wie schuetzt du den Zugriff wenn queue.size() > wie der Buffer receivedData ist ?
die Signatur der Funktion allein sieht schon irgendwie gefährlich aus :-)
Und noch was zum nachdenken:
m_tcpsocket schreibt in nen Lokalen buffer (QByteArray)
Der lokale buffer wird zeichen für zeichen in nen globalen buffer(queue) kopiert.
-> Signalhandling.
Der gloabe buffer wird zeichen für zeichen in einen weiteren buffer(receivedData) kopiert ...
Ich vermute das alles alles läuft im mainthread :-)
Also ueber wenig Arbeit braucht sich dein Speichercontroller ned zu beschweren ^^
warum er manchmal nicht auf den TCP Socket zugreifen kann.
Ohne weiteren code zu sehen kann ich ned viel sagen, aber ich vermute das dein Socket nicht das Problem ist, sondern er nur zu dem zeitpunkt da rausfliegt ...
Der Debugger springt manchmal nicht an die 100% richtige Stelle, bei multithreaded und wenn es zu systemfehlern kommt.
Ist aber nur ne Vermutung ....
Muss ich das noch irgendwie mit Semaphoren schützen?
Wer erzeugt die TCPSocket Instance und wer m_tcpSocket(QTcpSocket nehm ich an) ?
Wenn die alle "Normal" also ohne QThread oder QtConcurrent Zeugs erzeugt wurden, laufen der MsgLoops im GUI(Main)-Thread.
D.h. die assynchronitaet vom Netzwerk wird dir von QTcpSocket schon in den GUI-Thread gemappt, aka du hasst danach kein multithreading mehr und brauchst gar nichts schützen ^^

DIe Frage ist, was willst du ? schnell ne Lösung ? oder Netzwerk lernen und verstehen ?
willst du richtiges Multithreading oder langts wenn die empfangenen Daten in den Mainthread gemappt werden ?

Ciao ...
Ozzy
Beiträge: 141
Registriert: 24. Oktober 2007 10:18

Re: SIGSEGV bei TCP Socket

Beitrag von Ozzy »

Hi,

erst einmal vielen Dank für Deine Antwort! Deine erste Antwort hat schon gut was geliefert: der Buffer war zu klein. Hatte den mal auf 500Bytes gesetzt, da kam er mit den 2000 natürlich nicht klar...
ich werde mir aber auch noch etwas besseres überlegen, um die Daten weiterzugeben. Oder hast Du da vielleicht noch einen guten Vorschlag?

Vielen Dank
Ozzy
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: SIGSEGV bei TCP Socket

Beitrag von RHBaum »

Oder hast Du da vielleicht noch einen guten Vorschlag?
Generell würd ich immer empfehlen, auch mal nicht Qt biblios (boost::asio z.b.) anzuschauen .... Da wird man etwas sensibler was die Problematiken rund um Streams und Assynchronität angeht.
Ob man dann Qt vewendet oder nicht ist nen ganz anderes Blatt. Da kenn ich die Anforderungen zu wenig ... Performance, Datendurchsatz, latenz ....
Sind die Anforderungen gering, aka alles nicht kritisch, spricht nix dagegen sich das Leben leicht zu machen (90/10 Regel)

Ciao ...
Antworten