Segmentation fault when deleting a QSslSocket with delete / deleteLater()



  • Hello there,
    I have a big problem with the QSslSocket.
    I've developed an multithreaded application where a
    QTcpServer runs in the main thread, and the QSslSocket runs
    in the Thread.
    Everytime a new connections comes in, a new thread is created
    and the socket descriptor is handed to the new thread.
    @void Server::incomingConnection(int socketDescriptor){
    QThread* thread = new QThread;
    Worker* worker = new Worker(socketDescriptor);
    worker->moveToThread(thread);
    connect(worker, SIGNAL(errorThread(QString)), this, SLOT(errorThread(QString)));
    connect(thread, SIGNAL(started()), worker, SLOT(process()));
    connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->start();
    }@

    The constructor of the thread looks as following

    @Worker::Worker(int id)
    {
    this->socketDescriptor = id;
    }@

    the process mehtod which is called when the thread is started initializes the variables and sets the SSL connection
    @void Worker::process(){
    _st = Settings::getInstance();

    //initialize variables
    sslSocket = 0;
    requestData = "";
    finishedEmitted= false;
    closeConnectionCalled = false;
    
        sslSocket = new QSslSocket(0);
        if(sslSocket->setSocketDescriptor(socketDescriptor)){
    
            QString serverKeyPath = _st->serverPrivateKey;
            QString intermediateCertPath = _st->serverIntermediateCert;
    
            sslSocket->ignoreSslErrors();
            sslSocket->setCiphers(QSslSocket::supportedCiphers());
            sslSocket->setProtocol(QSsl::AnyProtocol);
            sslSocket->setPeerVerifyMode(QSslSocket::VerifyNone);
            sslSocket->setPrivateKey(serverKeyPath);
    
            sslSocket->setLocalCertificate(QSslCertificate::fromPath(_st->serverCertificate)[0]);
    
            if(intermediateCertPath.count()>0){
                sslSocket->addExtraCertificate(QSslCertificate::fromPath(_st->serverIntermediateCert)[0]);
            }else{
                sslSocket->addExtraCertificate(QSslCertificate::fromPath(_st->serverCertificate)[0]);
            }
    
            connect(sslSocket,SIGNAL(sslErrors(QList<QSslError>)),this,SLOT(sslError(QList<QSslError>)),Qt::DirectConnection);
            connect(sslSocket,SIGNAL(readyRead()),this,SLOT(readyRead()),Qt::DirectConnection);
            connect(sslSocket,SIGNAL(disconnected()),this,SLOT(disconnected()),Qt::DirectConnection);
            connect(sslSocket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(socketError(QAbstractSocket::SocketError)),Qt::DirectConnection);
            sslSocket->startServerEncryption();
    
    
            bool success = sslSocket->waitForReadyRead(10000);
            if(!success){
                sslSocket->abort();
                finish();
            }
    

    }@

    The readyread method reads all input data with sslSocket->redAll(); Then the inputdata
    gets processed and the output data is written with the following code

    @bool Worker::sendOutput(){
    bool ok;
    QString toSend = Json::serialize(output,ok);
    if(ok)
    {
    QByteArray bytes = toSend.toAscii();
    sslSocket->write(bytes);
    sslSocket->waitForBytesWritten(5000);
    return true;
    }
    return false;
    }@

    after that, the finish emthod is invoked at the end of the readyread method.

    @void Worker::finish(){
    if(!finishedEmitted){
    finishedEmitted = true;
    closeConnection();
    mutex.lock();
    mutex.unlock();
    if(sslSocket){
    sslSocket->blockSignals(true);
    sslSocket->disconnect();
    //sslSocket->deleteLater();
    delete sslSocket;
    sslSocket = 0;
    }
    emit finished();
    }
    }@

    here's the code for the closeConnection method

    @void Worker::closeConnection(){
    if(closeConnectionCalled)
    return;

        if(sslSocket){
            mutex.lock();
            if(sslSocket->isValid() && sslSocket->isOpen() && !closeConnectionCalled){
                closeConnectionCalled = true;
                sslSocket->close();
            }
            mutex.unlock();
        }
    

    }@

    As soon as I delete the sslSocket object, I got a segmentation fault.
    It plays no role whether I delete the object as in the code or above,
    or with sslObject->deleteLater.
    I also tried to delete the sslSocket in the destructor of the worker thread,
    but I got the same errors there.
    I really have no clue why this is happening ...
    Has anyone an clue ?
    The rest is just working fine, the peer sends his data, it's being written to a database,
    and the peer receives the server answer.
    Greetings Till


  • Lifetime Qt Champion

    Hi,

    I would advise you to recheck your locking i.e in finish you lock and unlock the mutex one after the other. Also you're not checking if sslSocket exists in sendOutput.

    Since QSslSocket is a QObject, you could also use a QPointer.

    Hope it helps


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.