fix ghastly deadlock/crash during exit
authorChristian Pulvermacher <christian@hazel.(none)>
Thu, 7 Oct 2010 18:13:06 +0000 (20:13 +0200)
committerChristian Pulvermacher <christian@hazel.(none)>
Thu, 7 Oct 2010 18:13:06 +0000 (20:13 +0200)
src/.mainwindow.cpp.swp [new file with mode: 0644]
src/.vncclientthread.cpp.swp [new file with mode: 0644]
src/.vncview.cpp.swp [new file with mode: 0644]
src/mainwindow.cpp
src/vncclientthread.cpp
src/vncclientthread.h
src/vncview.cpp

diff --git a/src/.mainwindow.cpp.swp b/src/.mainwindow.cpp.swp
new file mode 100644 (file)
index 0000000..98974bb
Binary files /dev/null and b/src/.mainwindow.cpp.swp differ
diff --git a/src/.vncclientthread.cpp.swp b/src/.vncclientthread.cpp.swp
new file mode 100644 (file)
index 0000000..9722f6e
Binary files /dev/null and b/src/.vncclientthread.cpp.swp differ
diff --git a/src/.vncview.cpp.swp b/src/.vncview.cpp.swp
new file mode 100644 (file)
index 0000000..ba8e9f4
Binary files /dev/null and b/src/.vncview.cpp.swp differ
index fb9d4c8..71950be 100644 (file)
@@ -141,8 +141,6 @@ MainWindow::MainWindow(QString url, int quality):
                vnc_view->start();
                key_menu = new KeyMenu(this);
        }
-
-       //QTimer::singleShot(500, this, SLOT(close()));
 }
 
 void MainWindow::grabZoomKeys(bool grab)
@@ -216,7 +214,6 @@ void MainWindow::disconnectFromHost()
 
        scroll_area->setWidget(0);
 
-       vnc_view->disconnect(); //remove all signal-slot connections
        delete vnc_view;
        vnc_view = 0;
        disconnect_action->setEnabled(false);
@@ -265,6 +262,8 @@ void MainWindow::statusChanged(RemoteView::RemoteStatus status)
                        scroll_area->setWidget(0); //remove widget
                }
                break;
+       default: //avoid compiler warnings
+               break;
        }
 
        old_status = status;
index dadf93d..95b418a 100644 (file)
@@ -91,9 +91,6 @@ void VncClientThread::updatefb(rfbClient* cl, int x, int y, int w, int h)
     VncClientThread *t = (VncClientThread*)rfbClientGetClientData(cl, 0);
     Q_ASSERT(t);
 
-    if (t->m_stopped)
-        return; //sending data to a stopped thread is not a good idea
-
     t->setImage(img);
 
     t->emitUpdated(x, y, w, h);
@@ -177,14 +174,11 @@ VncClientThread::~VncClientThread()
 
     const bool quitSuccess = wait(1000);
 
-    kDebug(5011) << "~VncClientThread(): Quit VNC thread success:" << quitSuccess;
+       if(!quitSuccess)
+               kDebug(5011) << "~VncClientThread(): Quit failed";
     
     delete [] frameBuffer;
     //cl is free()d when event loop exits.
-
-       kDebug(5011) << "inMessageHandler: " << inMessageHandler;
-
-       kDebug(5011) << "leaving ~VncClientThreod()";
 }
 
 void VncClientThread::checkOutputErrorMessage()
@@ -250,9 +244,7 @@ void VncClientThread::emitGotCut(const QString &text)
 void VncClientThread::stop()
 {
     QMutexLocker locker(&mutex);
-//TODO: not locking the mutex leads to a crash, but at least it stops.
-//TODO: i don't see how this makes a difference
-       kDebug(5011) << "stop(): mutex locked";
+
     m_stopped = true;
 }
 
@@ -303,28 +295,15 @@ void VncClientThread::run()
 
     locker.unlock();
 
-       inMessageHandler = false;
-
     // Main VNC event loop
     while (!m_stopped) {
         const int i = WaitForMessage(cl, 500);
-        if (i < 0)
-            break;
-               if(m_stopped) {
-                       kDebug(5011) << "foo2";
+               if(m_stopped or i < 0)
                        break;
-               }
-        if (i) {
-                       inMessageHandler = true;
+
+        if (i)
             if (!HandleRFBServerMessage(cl))
                 break;
-                       inMessageHandler = false;
-               }
-
-               if(m_stopped) {
-                       kDebug(5011) << "foo4";
-                       break;
-               }
 
         locker.relock();
 
@@ -336,15 +315,12 @@ void VncClientThread::run()
 
         locker.unlock();
     }
-       kDebug(5011) << "exited main loop";
 
     // Cleanup allocated resources
     locker.relock();
-       kDebug(5011) << "mutex relocked";
        if(!clean)
                rfbClientCleanup(cl);
     m_stopped = true;
-       kDebug(5011) << "exiting run()";
 }
 
 ClientEvent::~ClientEvent()
index 7135003..6940cad 100644 (file)
@@ -149,7 +149,6 @@ private:
 
     volatile bool m_stopped;
     volatile bool m_passwordError;
-       bool inMessageHandler;
 
 private slots:
     void checkOutputErrorMessage();
index c4cc1c3..fd157c8 100644 (file)
@@ -75,6 +75,7 @@ VncView::VncView(QWidget *parent, const KUrl &url, RemoteView::Quality quality)
     m_host = url.host();
     m_port = url.port();
 
+       //BlockingQueuedConnection can cause deadlocks when exiting, handled in startQuitting()
     connect(&vncThread, SIGNAL(imageUpdated(int, int, int, int)), this, SLOT(updateImage(int, int, int, int)), Qt::BlockingQueuedConnection);
     connect(&vncThread, SIGNAL(gotCut(const QString&)), this, SLOT(setCut(const QString&)), Qt::BlockingQueuedConnection);
     connect(&vncThread, SIGNAL(passwordRequest()), this, SLOT(requestPassword()), Qt::BlockingQueuedConnection);
@@ -137,23 +138,24 @@ void VncView::startQuitting()
 {
     kDebug(5011) << "about to quit";
 
-    const bool connected = status() == RemoteView::Connected;
+    //const bool connected = status() == RemoteView::Connected;
 
     setStatus(Disconnecting);
 
     m_quitFlag = true;
 
-    if (connected) {
-               kDebug(5011) << "stopping vncThread";
-        vncThread.stop();
-    }
-
-    vncThread.quit();
+       //if(connected) //remove if things work without it
+       vncThread.stop();
 
     const bool quitSuccess = vncThread.wait(700);
-
-    kDebug(5011) << "startQuitting(): Quit VNC thread success:" << quitSuccess;
-
+       if(!quitSuccess) {
+               //happens when vncThread wants to call a slot via BlockingQueuedConnection,
+               //needs an event loop in this thread so execution continues after 'emit'
+               QEventLoop loop;
+               if(!loop.processEvents())
+                       kDebug(5011) << "BUG: deadlocked, but no events to deliver?";
+               vncThread.wait(700);
+       }
     setStatus(Disconnected);
 }
 
@@ -271,6 +273,7 @@ void VncView::updateImage(int x, int y, int w, int h)
        if(!QApplication::focusWidget()) { //no focus, we're probably minimized
                return;
        }
+
      //kDebug(5011) << "got update" << width() << height();
 
      /*