From b487c8b74252ac995d183da8908414238b00cb72 Mon Sep 17 00:00:00 2001 From: Manuel Schneider Date: Wed, 23 Apr 2014 18:10:36 +0200 Subject: Made vnc thread stoppable from outside. Thread kills itself. If the vnc connection cannot be established a timeout kills the thread after a short period of time. --- src/client/vnc/vncthread.cpp | 80 +++++++++++++++++++++----------------------- src/client/vnc/vncthread.h | 1 + src/client/vnc/vncwindow.cpp | 58 +++++++++++++++++--------------- src/client/vnc/vncwindow.h | 3 +- 4 files changed, 72 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/client/vnc/vncthread.cpp b/src/client/vnc/vncthread.cpp index 86db840..068a88d 100644 --- a/src/client/vnc/vncthread.cpp +++ b/src/client/vnc/vncthread.cpp @@ -45,11 +45,8 @@ VncThread::VncThread(QString host, int port, QString passwd, int quality) : // ALWAYS delete this class from another thread using delete, not deleteLater, or you will deadlock the thread VncThread::~VncThread() { - qDebug("VNC worker destructor called, waiting for thread finishing..."); - _run = false; - while (this->isRunning()) - this->msleep(10); - qDebug("Thread ended."); + qDebug("VNC worker destructor called."); + Q_ASSERT(_run == false); if (_frameBuffer) delete[] _frameBuffer; if (_client != NULL) @@ -118,50 +115,49 @@ void VncThread::run() if (!rfbInitClient(_client, NULL, NULL)) { _client = NULL; // !!! <- if you don't do this you will get a segfault later when you try to clean up _client, as rfbInitClient already did so - this->stop(); - return; } - - qDebug("[%s] Connection successful!", metaObject()->className()); - int one = 1; - setsockopt(_client->sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one)); - one = 1; - setsockopt(_client->sock, SOL_TCP, TCP_QUICKACK, &one, sizeof(one)); - - // Main VNC event loop - emit projectionStarted(); - while (_run) + else { - _connected = true; - const int i = WaitForMessage(_client, 100 * 1000); // wait 100ms for message. returns -1 on error/disconnect, 0 if nothing happened, 1 if new data arrived - if (i < 0) - break; - if (i > 0 && !HandleRFBServerMessage(_client)) - break; - - if (_hasNewLocalSize) + qDebug("[%s] Connection successful!", metaObject()->className()); + int one = 1; + setsockopt(_client->sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one)); + one = 1; + setsockopt(_client->sock, SOL_TCP, TCP_QUICKACK, &one, sizeof(one)); + + // Main VNC event loop + emit projectionStarted(); + } + + if(_client != NULL) + while (_run) { - QMutexLocker lock(&_mutex); - _hasNewLocalSize = false; - _localSize = _newLocalSize; - if (_painter != NULL) - delete _painter; - _imgScaled = QImage(_localSize, QImage::Format_RGB32); - _painter = new QPainter(&_imgScaled); - this->calcScaling(); + _connected = true; + const int i = WaitForMessage(_client, 100 * 1000); // wait 100ms for message. returns -1 on error/disconnect, 0 if nothing happened, 1 if new data arrived + if (i < 0) + break; + if (i > 0 && !HandleRFBServerMessage(_client)) + break; + + if (_hasNewLocalSize) + { + QMutexLocker lock(&_mutex); + _hasNewLocalSize = false; + _localSize = _newLocalSize; + if (_painter != NULL) + delete _painter; + _imgScaled = QImage(_localSize, QImage::Format_RGB32); + _painter = new QPainter(&_imgScaled); + this->calcScaling(); + } } - /* - //work yourself through event queue and fire every event... - while (!_eventQueue.isEmpty()) { - SomeEvent* event = _eventQueue.dequeue(); - event->fire(_client); - delete event; - }*/ - } - _connected = false; + emit projectionStopped(); + while (_run) + this->msleep(100); qDebug("[%s] VNC client stopped.", metaObject()->className()); + this->deleteLater(); + QThread::run(); } const QString VncThread::getDesktopName() const diff --git a/src/client/vnc/vncthread.h b/src/client/vnc/vncthread.h index 23530ec..17e991d 100644 --- a/src/client/vnc/vncthread.h +++ b/src/client/vnc/vncthread.h @@ -133,6 +133,7 @@ public: signals: void imageUpdated(const int x, const int y, const int w, const int h); void projectionStarted(); + void projectionStopped(); }; diff --git a/src/client/vnc/vncwindow.cpp b/src/client/vnc/vncwindow.cpp index f55aa28..34cbab7 100644 --- a/src/client/vnc/vncwindow.cpp +++ b/src/client/vnc/vncwindow.cpp @@ -35,11 +35,13 @@ VncWindow::~VncWindow() void VncWindow::open(const QString& host, int port, const QString& passwd, bool ro, bool fullscreen, const QString& caption, const int clientId) { // start thread for vnc-updates - this->onThreadFinished(); + this->onProjectionStopped(); _clientId = clientId; _vncWorker = new VncThread(host, port, passwd, 1); - connect(_vncWorker, SIGNAL(finished()), this, SLOT(onThreadFinished()), Qt::QueuedConnection); + connect(_vncWorker, SIGNAL(projectionStopped()), this, SLOT(onProjectionStopped()), Qt::QueuedConnection); connect(_vncWorker, SIGNAL(projectionStarted()), this, SLOT(onProjectionStarted()), Qt::QueuedConnection); + + _tcpTimeoutTimer = startTimer(4000); _vncWorker->start(QThread::LowPriority); //_rfbclient = _thread->getRfbClient(); //installEventFilter(this); @@ -67,7 +69,7 @@ void VncWindow::open(const QString& host, int port, const QString& passwd, bool _vncWorker->setTargetSize(this->size()); connect(_vncWorker, SIGNAL(imageUpdated(const int, const int, const int, const int)), this, - SLOT(onUpdateImage(const int, const int, const int, const int)), + SLOT(onUpdateImage(const int, const int, const int, const int)), Qt::QueuedConnection); } @@ -76,7 +78,7 @@ void VncWindow::closeEvent(QCloseEvent *e) e->ignore(); qDebug("Closing VNC viewer window."); this->setVisible(false); - this->onThreadFinished(); + this->onProjectionStopped(); emit running(false, _clientId); } @@ -85,35 +87,30 @@ void VncWindow::onUpdateImage(const int x, const int y, const int w, const int h this->repaint(x, y, w, h); } -/** - * Thread finished, clean up and close window - */ -void VncWindow::onThreadFinished() -{ - if (_vncWorker) - { - disconnect(_vncWorker, SIGNAL(imageUpdated(const int, const int, const int, const int)), this, - SLOT(onUpdateImage(const int, const int, const int, const int))); - disconnect(_vncWorker, SIGNAL(finished()), this, SLOT(onThreadFinished())); - _vncWorker->stop(); - delete _vncWorker; - _vncWorker = NULL; - this->close(); - } - if(_redrawTimer != 0) - { - killTimer(_redrawTimer); - _redrawTimer = 0; - } -} - /** * VNC Thread successfully connected to remote end - projection will start */ void VncWindow::onProjectionStarted() { emit running(true, _clientId); - //_redrawTimer = startTimer(5000); + _redrawTimer = startTimer(5000); +} + +void VncWindow::onProjectionStopped() +{ + if(_vncWorker == NULL) + return; + + _vncWorker->blockSignals(true); + _vncWorker->stop(); + _vncWorker = NULL; + if(_redrawTimer != 0) + { + killTimer(_redrawTimer); + _redrawTimer = 0; + } + this->close(); + } //////////////////////////////////////////////////////////////////////////////// @@ -126,6 +123,13 @@ void VncWindow::timerEvent(QTimerEvent *event) if (this->isVisible()) this->repaint(); } + else if (event->timerId() == _tcpTimeoutTimer) + { + killTimer(_tcpTimeoutTimer); + if (_vncWorker != NULL && !_vncWorker->isConnected()){ + this->onProjectionStopped(); + } + } else killTimer(event->timerId()); } diff --git a/src/client/vnc/vncwindow.h b/src/client/vnc/vncwindow.h index 396e2de..60e4835 100644 --- a/src/client/vnc/vncwindow.h +++ b/src/client/vnc/vncwindow.h @@ -37,8 +37,8 @@ public: protected slots: void onUpdateImage(const int x, const int y, const int w, const int h); - void onThreadFinished(); void onProjectionStarted(); + void onProjectionStopped(); void open(const QString& host, int port, const QString& passwd, bool ro, bool fullscreen, const QString& caption, const int clientId); @@ -62,6 +62,7 @@ private: QMap _modkeys; int _clientId; int _redrawTimer; + int _tcpTimeoutTimer; bool eventFilter(QObject *obj, QEvent *event); void keyPressEvent(QKeyEvent* event); -- cgit v1.2.3-55-g7522