Properly terminate server on timeouts
Do a proper cleanup when one of the termination timeouts trigger
rather than just exiting on the spot. This makes sure we don't leave
stray stuff around, e.g. unix socket files.
diff --git a/common/rfb/SDesktop.h b/common/rfb/SDesktop.h
index 6118246..0060aa2 100644
--- a/common/rfb/SDesktop.h
+++ b/common/rfb/SDesktop.h
@@ -75,6 +75,12 @@
virtual void queryConnection(network::Socket* sock,
const char* userName) = 0;
+ // terminate() is called by the server when it wishes to terminate
+ // itself, e.g. because it was configured to terminate when no one is
+ // using it.
+
+ virtual void terminate() = 0;
+
// setScreenLayout() requests to reconfigure the framebuffer and/or
// the layout of screens.
virtual unsigned int setScreenLayout(int __unused_attr fb_width,
diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx
index 352b80f..601e636 100644
--- a/common/rfb/VNCServerST.cxx
+++ b/common/rfb/VNCServerST.cxx
@@ -574,13 +574,13 @@
return true;
} else if (t == &idleTimer) {
slog.info("MaxIdleTime reached, exiting");
- exit(0);
+ desktop->terminate();
} else if (t == &disconnectTimer) {
slog.info("MaxDisconnectionTime reached, exiting");
- exit(0);
+ desktop->terminate();
} else if (t == &connectTimer) {
slog.info("MaxConnectionTime reached, exiting");
- exit(0);
+ desktop->terminate();
}
return false;
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx
index 9a047c8..3e67fad 100644
--- a/unix/x0vncserver/XDesktop.cxx
+++ b/unix/x0vncserver/XDesktop.cxx
@@ -19,6 +19,8 @@
*/
#include <assert.h>
+#include <signal.h>
+#include <unistd.h>
#include <rfb/LogWriter.h>
@@ -273,6 +275,10 @@
pb = 0;
}
+void XDesktop::terminate() {
+ kill(getpid(), SIGTERM);
+}
+
bool XDesktop::isRunning() {
return running;
}
diff --git a/unix/x0vncserver/XDesktop.h b/unix/x0vncserver/XDesktop.h
index 7d06061..3e85aac 100644
--- a/unix/x0vncserver/XDesktop.h
+++ b/unix/x0vncserver/XDesktop.h
@@ -49,6 +49,7 @@
// -=- SDesktop interface
virtual void start(rfb::VNCServer* vs);
virtual void stop();
+ virtual void terminate();
bool isRunning();
virtual void queryConnection(network::Socket* sock,
const char* userName);
diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
index e61472b..d4891c3 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.cc
+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
@@ -22,6 +22,7 @@
//
#include <assert.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
@@ -423,6 +424,11 @@
// SDesktop callbacks
+void XserverDesktop::terminate()
+{
+ kill(getpid(), SIGTERM);
+}
+
void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
{
vncPointerMove(pos.x + vncGetScreenX(screenIndex),
diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
index ff36b3b..1253935 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.h
+++ b/unix/xserver/hw/vnc/XserverDesktop.h
@@ -87,6 +87,7 @@
// rfb::SDesktop callbacks
virtual void start(rfb::VNCServer* vs);
virtual void stop();
+ virtual void terminate();
virtual void queryConnection(network::Socket* sock,
const char* userName);
virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
diff --git a/win/rfb_win32/SDisplay.cxx b/win/rfb_win32/SDisplay.cxx
index afb72ad..2cedc4a 100644
--- a/win/rfb_win32/SDisplay.cxx
+++ b/win/rfb_win32/SDisplay.cxx
@@ -71,6 +71,7 @@
statusLocation(0), queryConnectionHandler(0), ledState(0)
{
updateEvent.h = CreateEvent(0, TRUE, FALSE, 0);
+ terminateEvent.h = CreateEvent(0, TRUE, FALSE, 0);
}
SDisplay::~SDisplay()
@@ -140,6 +141,11 @@
if (statusLocation) *statusLocation = false;
}
+void SDisplay::terminate()
+{
+ SetEvent(terminateEvent);
+}
+
void SDisplay::queryConnection(network::Socket* sock,
const char* userName)
diff --git a/win/rfb_win32/SDisplay.h b/win/rfb_win32/SDisplay.h
index 76ddf50..6dbfabb 100644
--- a/win/rfb_win32/SDisplay.h
+++ b/win/rfb_win32/SDisplay.h
@@ -72,6 +72,7 @@
virtual void start(VNCServer* vs);
virtual void stop();
+ virtual void terminate();
virtual void queryConnection(network::Socket* sock,
const char* userName);
virtual void pointerEvent(const Point& pos, int buttonmask);
@@ -89,6 +90,7 @@
// -=- EventHandler interface
HANDLE getUpdateEvent() {return updateEvent;}
+ HANDLE getTerminateEvent() {return terminateEvent;}
virtual void processEvent(HANDLE event);
// -=- Notification of whether or not SDisplay is started
@@ -161,6 +163,8 @@
// -=- Event signalled to trigger an update to be flushed
Handle updateEvent;
+ // -=- Event signalled to terminate the server
+ Handle terminateEvent;
// -=- Where to write the active/inactive indicator to
bool* statusLocation;
diff --git a/win/winvnc/VNCServerWin32.cxx b/win/winvnc/VNCServerWin32.cxx
index 03b1bca..e001449 100644
--- a/win/winvnc/VNCServerWin32.cxx
+++ b/win/winvnc/VNCServerWin32.cxx
@@ -76,6 +76,7 @@
// Register the desktop's event to be handled
sockMgr.addEvent(desktop.getUpdateEvent(), &desktop);
+ sockMgr.addEvent(desktop.getTerminateEvent(), this);
// Register the queued command event to be handled
sockMgr.addEvent(commandEvent, this);
@@ -335,7 +336,8 @@
command = NoCommand;
commandSig->signal();
}
- } else if (event_ == sessionEvent.h) {
+ } else if ((event_ == sessionEvent.h) ||
+ (event_ == desktop.getTerminateEvent())) {
stop();
}
}