From 90abc79efa3d7ca6ac10c5f3bc329ec128008523 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Wed, 22 Nov 2023 13:02:35 +0900 Subject: [PATCH] krfb: fix termination and syncing of threads on exit. This resolves issue #2. Signed-off-by: Michele Calgaro --- libvncserver/main.cpp | 50 +++++++++++++++++++++++++++---------------- libvncserver/main.h | 24 ++++++++++++++++++--- 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/libvncserver/main.cpp b/libvncserver/main.cpp index 7765302..549e77f 100644 --- a/libvncserver/main.cpp +++ b/libvncserver/main.cpp @@ -466,13 +466,13 @@ void rfbMarkRectAsModified(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2) #include static void * -clientOutput(void *data) +clientOutput(ClientOutputHandlerObject::Data d) { - rfbClientPtr cl = (rfbClientPtr)data; + rfbClientPtr cl = d.rfbData; rfbBool haveUpdate; sraRegion* updateRegion; - while (1) { + while (!d.requestExit) { haveUpdate = false; while (!haveUpdate) { if (cl->sock == -1) { @@ -532,18 +532,18 @@ clientOutput(void *data) } static void * -clientInput(void *data) +clientInput(OnHoldClientHandlerObject::Data d) { - rfbClientPtr cl = (rfbClientPtr)data; + rfbClientPtr cl = d.rfbData; /* Start output thread */ TQEventLoopThread* clientOutputHandlerThread = new TQEventLoopThread(); ClientOutputHandlerObject* clientOutputHandler = new ClientOutputHandlerObject(); - clientOutputHandler->d = cl; + clientOutputHandler->d.rfbData = cl; clientOutputHandler->moveToThread(clientOutputHandlerThread); TQTimer::singleShot(0, clientOutputHandler, TQ_SLOT(run())); clientOutputHandlerThread->start(); - while (1) { + while (!d.requestExit) { fd_set rfds, wfds, efds; struct timeval tv; int n; @@ -589,7 +589,7 @@ clientInput(void *data) { /* Reset the pipe */ char buf; - while (read(cl->pipe_notify_client_thread[0], &buf, sizeof(buf)) == sizeof(buf)); + while (!d.requestExit && read(cl->pipe_notify_client_thread[0], &buf, sizeof(buf)) == sizeof(buf)); } if (FD_ISSET(cl->sock, &rfds) || FD_ISSET(cl->sock, &efds)) @@ -597,7 +597,7 @@ clientInput(void *data) #ifdef LIBVNCSERVER_WITH_WEBSOCKETS do { rfbProcessClientMessage(cl); - } while (webSocketsHasDataInBuffer(cl)); + } while (!d.requestExit && webSocketsHasDataInBuffer(cl)); #else rfbProcessClientMessage(cl); #endif @@ -608,6 +608,7 @@ clientInput(void *data) LOCK(cl->updateMutex); TSIGNAL(cl->updateCond); UNLOCK(cl->updateMutex); + clientOutputHandler->requestExit(); clientOutputHandlerThread->wait(); delete clientOutputHandlerThread; clientOutputHandlerThread = NULL; @@ -620,9 +621,9 @@ clientInput(void *data) } static void* -listenerRun(void *data) +listenerRun(ControlPipeHandlerObject::Data d) { - rfbScreenInfoPtr screen=(rfbScreenInfoPtr)data; + rfbScreenInfoPtr screen=d.rfbData; int client_fd; struct sockaddr_storage peer; rfbClientPtr cl = NULL; @@ -640,7 +641,7 @@ listenerRun(void *data) /* TODO: this thread won't die by restarting the server */ /* TODO: HTTP is not handled */ - while (1) { + while (!d.requestExit) { client_fd = -1; FD_ZERO(&listen_fds); if(screen->listenSock >= 0) @@ -673,7 +674,7 @@ rfbStartOnHoldClient(rfbClientPtr cl) { mOnHoldClientHandlerThread = new TQEventLoopThread(); mOnHoldClientHandler = new OnHoldClientHandlerObject(); - mOnHoldClientHandler->d = cl; + mOnHoldClientHandler->d.rfbData = cl; mOnHoldClientHandler->moveToThread(mOnHoldClientHandlerThread); TQTimer::singleShot(0, mOnHoldClientHandler, TQ_SLOT(run())); mOnHoldClientHandlerThread->start(); @@ -1097,17 +1098,28 @@ void rfbScreenCleanup(rfbScreenInfoPtr screen) } rfbReleaseClientIterator(i); + if (mOnHoldClientHandler) { + mOnHoldClientHandler->requestExit(); + } if (mOnHoldClientHandlerThread) { - mOnHoldClientHandlerThread->exit(); + mOnHoldClientHandlerThread->wait(); delete mOnHoldClientHandlerThread; mOnHoldClientHandlerThread = NULL; + } + if (mOnHoldClientHandler) { delete mOnHoldClientHandler; mOnHoldClientHandler = NULL; } + + if (mControlPipeHandler) { + mControlPipeHandler->requestExit(); + } if (mControlPipeHandlerThread) { - mControlPipeHandlerThread->exit(); + mControlPipeHandlerThread->wait(); delete mControlPipeHandlerThread; mControlPipeHandlerThread = NULL; + } + if (mControlPipeHandler) { delete mControlPipeHandler; mControlPipeHandler = NULL; } @@ -1305,7 +1317,7 @@ void rfbRunEventLoop(rfbScreenInfoPtr screen, long usec, rfbBool runInBackground mControlPipeHandlerThread = new TQEventLoopThread(); mControlPipeHandler = new ControlPipeHandlerObject(); - mControlPipeHandler->d = screen; + mControlPipeHandler->d.rfbData = screen; mControlPipeHandler->moveToThread(mControlPipeHandlerThread); TQTimer::singleShot(0, mControlPipeHandler, TQ_SLOT(run())); mControlPipeHandlerThread->start(); @@ -1324,7 +1336,7 @@ void rfbRunEventLoop(rfbScreenInfoPtr screen, long usec, rfbBool runInBackground } ControlPipeHandlerObject::ControlPipeHandlerObject() : TQObject() { - // + d.requestExit = false; } ControlPipeHandlerObject::~ControlPipeHandlerObject() { @@ -1339,7 +1351,7 @@ void ControlPipeHandlerObject::run(void) { } OnHoldClientHandlerObject::OnHoldClientHandlerObject() : TQObject() { - // + d.requestExit = false; } OnHoldClientHandlerObject::~OnHoldClientHandlerObject() { @@ -1354,7 +1366,7 @@ void OnHoldClientHandlerObject::run(void) { } ClientOutputHandlerObject::ClientOutputHandlerObject() : TQObject() { - // + d.requestExit = false; } ClientOutputHandlerObject::~ClientOutputHandlerObject() { diff --git a/libvncserver/main.h b/libvncserver/main.h index 6c31980..1edd4cc 100644 --- a/libvncserver/main.h +++ b/libvncserver/main.h @@ -21,9 +21,15 @@ class ControlPipeHandlerObject : public TQObject public slots: void run(); + void requestExit() { d.requestExit = true; } public: - rfbScreenInfoPtr d; + struct Data + { + rfbScreenInfoPtr rfbData; + bool requestExit; + }; + Data d; }; class OnHoldClientHandlerObject : public TQObject @@ -36,9 +42,15 @@ class OnHoldClientHandlerObject : public TQObject public slots: void run(); + void requestExit() { d.requestExit = true; } public: - rfbClientPtr d; + struct Data + { + rfbClientPtr rfbData; + bool requestExit; + }; + Data d; }; class ClientOutputHandlerObject : public TQObject @@ -51,9 +63,15 @@ class ClientOutputHandlerObject : public TQObject public slots: void run(); + void requestExit() { d.requestExit = true; } public: - rfbClientPtr d; + struct Data + { + rfbClientPtr rfbData; + bool requestExit; + }; + Data d; }; #endif // _MAIN_H