Problem mit QSslSocket und delete / deleteLater()
Verfasst: 4. Mai 2013 10:14
Hallo Leute,
ich habe ein großes Problem mit SSLSockets, ich mache schon seit Tagen rum,
aber irgendwie finde ich die Lösung einfach nicht.
Ich habe einen Anwendung geschrieben welche Client Anfragen in Threads bearbeitet.
Im Main Thread läuft eine Klasse welche von QTcpServer abgeleitet ist, und deren incomingConnection wie folgt aussieht
Im Konstrukter der Worker Klasse wird der SocketDescriptor übergeben.
Die Prozess Methode initialisiert alle Variablen, und erstellt den QSslSocket auf dem Heap.
Soweit so gut, Ready Read wird ausgelöst, Daten werden mittels sslSocket->readAll eingelesen
und am Ende der ReadyRead Methode wird die finish Methode aufgerufen.
Das Einlesen der Daten funktioniert wunderbar, ebenso das bearbeiten, abspeichern
in der Datenbank und die Ausgabe des Ergebnisses.
Hier möchte ich nun das QSslSocket Objekt vom Heap löschen.
Der Code der finish Methode lautet wie folgt.
Sobald das Socket Objekt gelöscht wird, dabei spielt es keine Rolle ob in der finish Methode oder
im Destruktor, egal ob mit delete oder sslSocket->deleteLater, es gibt immer hässliche Segmentation Faults.
Wenn man mit dem Debugger reingeht sieht man dass diese entstehen wenn die geladenen Zertifkate
gelöscht werden sollen.
Wenn ich die Zertifikate anders wieim obigen Code so wie hier reinlade, gibt es ein Segmentation Fault beim
Versuch die QHostAddress zu deleten. wobei _st->certServerCertificate ein QSslCertificate ist.
Also irgendwie beschleicht mich das Gefühl das der Socket irgendwie zweimal ? deleted wird.
Hat jemand von Euch eine Idee, ich bin echt am verzweifeln ...
Ich hab schon sehr viel gegoogelt, aber keine ähnlichen Probleme gefunden.
Daraus schliese ich dass ich wohl etwas grundlegendes falsch mache ...
Gruß Till
ich habe ein großes Problem mit SSLSockets, ich mache schon seit Tagen rum,
aber irgendwie finde ich die Lösung einfach nicht.
Ich habe einen Anwendung geschrieben welche Client Anfragen in Threads bearbeitet.
Im Main Thread läuft eine Klasse welche von QTcpServer abgeleitet ist, und deren incomingConnection wie folgt aussieht
Code: Alles auswählen
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();
}
Code: Alles auswählen
Worker::Worker(int id)
{
this->socketDescriptor = id;
}Code: Alles auswählen
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();
}
}und am Ende der ReadyRead Methode wird die finish Methode aufgerufen.
Das Einlesen der Daten funktioniert wunderbar, ebenso das bearbeiten, abspeichern
in der Datenbank und die Ausgabe des Ergebnisses.
Hier möchte ich nun das QSslSocket Objekt vom Heap löschen.
Der Code der finish Methode lautet wie folgt.
Code: Alles auswählen
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();
}
}Code: Alles auswählen
void Worker::closeConnection(){
if(closeConnectionCalled)
return;
if(sslSocket){
mutex.lock();
if(sslSocket->isValid() && sslSocket->isOpen() && !closeConnectionCalled){
closeConnectionCalled = true;
sslSocket->close();
}
mutex.unlock();
}
}im Destruktor, egal ob mit delete oder sslSocket->deleteLater, es gibt immer hässliche Segmentation Faults.
Wenn man mit dem Debugger reingeht sieht man dass diese entstehen wenn die geladenen Zertifkate
gelöscht werden sollen.
Wenn ich die Zertifikate anders wieim obigen Code so wie hier reinlade, gibt es ein Segmentation Fault beim
Versuch die QHostAddress zu deleten. wobei _st->certServerCertificate ein QSslCertificate ist.
Code: Alles auswählen
QSslCertificate localCert = QSslCertificate(_st->certServerCertificate);
sslSocket->setLocalCertificate (localCert);
Hat jemand von Euch eine Idee, ich bin echt am verzweifeln ...
Ich hab schon sehr viel gegoogelt, aber keine ähnlichen Probleme gefunden.
Daraus schliese ich dass ich wohl etwas grundlegendes falsch mache ...
Gruß Till