Malwieder Sockets...

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Halan
Beiträge: 73
Registriert: 22.01.2005, 21:47
Benutzertext: programmiersüchtig
Echter Name: Kai Mast
Wohnort: Freak City
Kontaktdaten:

Malwieder Sockets...

Beitrag von Halan »

Hey,

ich habe über die letzen Monate immer wieder ab und zu an meiner Netwerk-Klasse geschrieben. Diese funktioniert - auch durch die Hilfe dieses Forum - jetzt eigentlich perfekt. Ich habe nurnoch ein sehr eigenartiges Problem dessen Lösung ich einfach nicht finden kann.

Ich benutze TCP als Protokoll und select() um herauszufinden, ob es etwas zu lesen/schreiben gibt. Dies funktioniert auch einwandfrei außer mein Client hat einen Segfault (nicht aufgrund des Netzwerk-Codes). Dann kann es passieren dass der Server beim Lesen des Sockets segfaulted. Das selbe passiert dass beim Neustart des Servers und dem Aufruf von bind(). Ein sehr komisches Verhalten dass auch nicht immer auftritt.

Hier der Code zum Empfangen von Daten:

Code: Alles auswählen

    void CTCPPort::processReceiving(PeerID id)
    {
        // Clear the buffer (global member)
        memset(&buffer[0], 0, TCP_BUFFER_SIZE);

        s32 readLength = recv( peers[id]->socketfd, &buffer[0], TCP_BUFFER_SIZE, 0);

        if (readLength < 0)
        {
#ifdef YOGI_WINDOWS
            if(errno == WSAETIMEDOUT)
#else
            if(errno == ETIMEDOUT)
#endif
                this->getCallback()->onPeerDisconnect(id, NetworkInfo_ConnectionTimeout);
            else
            {
                this->getCallback()->onPeerDisconnect(id, NetworkInfo_UnknownError);

                if(logger)
                  //! Debugger sagt der Segfault passiert hier was aber an sich unlogisch scheint.
                    logger->log(ELMT_Warning, std::string("yNetwork") + strerror(errno));
                else
                    perror("yNetwork");
            }

            this->removePeer(id);
        }
        else if (readLength == 0)
        {
            this->getCallback()->onPeerDisconnect(id, NetworkInfo_ConnectionClosed);
            this->removePeer(id);
        }
        else
        {
            // Setup the BitStream
            BitStream data(&buffer[0], readLength);

            // Loop until we finished reading
            while (data.getByteIndex() < data.getLength())
            {
                if (!peers[id]->msgCache)
                {
                    // The length of the message
                    u32 length = data.read<u32>();

                    // Check wheter the whole package was read
                    if (length <= ( data.getLength()-data.getByteIndex() ) )
                    {
                        BitStream message;
                        data.copyRawArray<c8>(&message, length);

                        if(encrypter && encrypter->isValid())
                        {
                            encrypter->decrypt(message);
                        }

                        message.setByteIndex(0);
                        u8 msgType = message.read<u8>();
                        c8* dataStr = message.readRawArray<c8>(message.getLength()-1);

                        this->getCallback()->onMessageReceived(id, msgType, dataStr, message.getLength()-1);

                        delete []dataStr;
                    }
                    else
                    {
                        peers[id]->msgCache = new BitStream(length);

                        // Append everything to the cache
                        // We would like to read lenght-5 but we can only read some of it
                        data.copyRawArray<c8>(peers[id]->msgCache, data.getLength()-data.getByteIndex(), true, false);
                    }
                }
                else
                {
                    // Calculate how much we have to read
                    u32 length = peers[id]->msgCache->getLength() - peers[id]->msgCache->getByteIndex();

                    // If we STILL didn't receive everything we just read a piece of it again
                    if (static_cast<u32>(readLength) < length)
                        length = readLength;

                    // Append data to the cache :)
                    data.copyRawArray<c8>(peers[id]->msgCache, length, true, false);

                    if (peers[id]->msgCache->isAtEnd())
                    {
                        if(encrypter && encrypter->isValid())
                        {
                            encrypter->decrypt(*peers[id]->msgCache);
                        }

                        peers[id]->msgCache->setByteIndex(0);
                        u8 msgType = peers[id]->msgCache->read<u8>();
                        c8* dataStr = peers[id]->msgCache->readRawArray<c8>(peers[id]->msgCache->getLength()-1);

                        // Everything was received!
                        this->getCallback()->onMessageReceived(id, msgType , dataStr, peers[id]->msgCache->getLength()-1);

                        // Clean up
                        delete peers[id]->msgCache;
                        delete []dataStr;
                        peers[id]->msgCache = 0;
                    }
                }
            }
        }
    }

Kann es sein dass strerror() einen Crash verursacht? Vielleicht wenn die errno einen unbekannten Wert hat? Das kann ich mir aber irgendwie nicht vorstellen.

gruß,
Halan
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: Malwieder Sockets...

Beitrag von kimmi »

Ohne mich jetzt genau mit Netzwerk-Programmierung auszukennen: hast du dich schon mal mit einem Debugger auf den prozess attached und dir den Callstack deines Segfaults angesehen?

Gruß Kimmi
Halan
Beiträge: 73
Registriert: 22.01.2005, 21:47
Benutzertext: programmiersüchtig
Echter Name: Kai Mast
Wohnort: Freak City
Kontaktdaten:

Re: Malwieder Sockets...

Beitrag von Halan »

kimmi hat geschrieben:Ohne mich jetzt genau mit Netzwerk-Programmierung auszukennen: hast du dich schon mal mit einem Debugger auf den prozess attached und dir den Callstack deines Segfaults angesehen?
Ja wie gesagt hab die Zeile markiert die mir der Callstack gezeigt hat.
Psycho
Establishment
Beiträge: 156
Registriert: 16.09.2002, 14:23

Re: Malwieder Sockets...

Beitrag von Psycho »

Und, sind alle Variablen gültig?
Auf welche ungültige Addresse versuchst Du zuzugreifen?

Wenn Du denkst, dass der Abschnitt mit dem Logging nicht zum Fehler führt: Mal probiert, einige Codeabschnitte auszukommentieren und zu prüfen, ob es dann immer noch abschmiert?
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: Malwieder Sockets...

Beitrag von kimmi »

Kann da Psycho nur zustimmen: Schau dir die VAriablen an, die ungültig sind und überwache diese, wann der Fehler auftritt.

Gruß Kimmi
Halan
Beiträge: 73
Registriert: 22.01.2005, 21:47
Benutzertext: programmiersüchtig
Echter Name: Kai Mast
Wohnort: Freak City
Kontaktdaten:

Re: Malwieder Sockets...

Beitrag von Halan »

Das Problem ist wirklcih dass es sehr selten auftritt und auch wirklich nur unter bestimmten umständen (Client stürtzt genau währen einer transaktion ab). Ich hab schon einige Testprogramme geschrieben die das reproduzieren sollen, aber als dort der Fehler behoben wurde trat er im eignetlichen Programm immernoch auf.

Jetzt hatte ich das ganze schon eine ganze Zeit nicht mehr. Werde hier posten wenn ich weiss ob es wieder auftritt. Vielleicht ist es auch ein Kernel Bug gewesen und tritt deswegen nicht mehr auf.
Antworten