Index: /trunk/src/VBox/Additions/x11/VBoxClient/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/Makefile.kmk	(revision 86870)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/Makefile.kmk	(revision 86871)
@@ -21,4 +21,7 @@
 # Use header files from our tree for randr and xinerama. and don't link but rather dlopen libXrand
 VBOX_WITH_DISTRO_XRAND_XINERAMA=
+
+# We don't yet have a seamless mode compilation flag, so define it here unconditionally.
+VBOX_WITH_SEAMLESS:=1
 
 #
@@ -46,9 +49,5 @@
 VBoxClient_SOURCES = \
 	main.cpp \
-	display-svga-x11.cpp \
-	seamless.cpp \
-	seamless-x11.cpp \
-	logging.cpp \
-	hostversion.cpp
+	logging.cpp
 
 VBoxDRMClient_TEMPLATE = NewVBoxGuestR3Exe
@@ -84,6 +83,6 @@
 ifdef VBOX_WITH_DRAG_AND_DROP
  ifdef VBOX_DND_WITH_XTEST
- VBoxClient_DEFS += VBOX_DND_WITH_XTEST
- VBoxClient_LIBS += \
+  VBoxClient_DEFS += VBOX_DND_WITH_XTEST
+  VBoxClient_LIBS += \
 	Xtst
  endif
@@ -94,28 +93,43 @@
 # how else to do that without recompiling or implementing our own memcpy.
 ifeq ($(KBUILD_TARGET),linux)
-VBoxClient_LDFLAGS.amd64 += \
+ VBoxClient_LDFLAGS.amd64 += \
 	-Wl,--wrap=memcpy
 endif
 
 ifdef VBOX_WITH_GUEST_PROPS
-VBoxClient_DEFS += VBOX_WITH_GUEST_PROPS
+ VBoxClient_DEFS    += VBOX_WITH_GUEST_PROPS
+ VBoxClient_SOURCES += \
+	hostversion.cpp
 endif
 
 ifdef VBOX_WITH_DRAG_AND_DROP
-VBoxClient_DEFS += \
+ VBoxClient_DEFS     += \
 	VBOX_WITH_DRAG_AND_DROP \
 	$(if $(VBOX_WITH_DRAG_AND_DROP_GH),VBOX_WITH_DRAG_AND_DROP_GH,)
-VBoxClient_SOURCES += \
+ VBoxClient_SOURCES  += \
 	draganddrop.cpp
-VBoxClient_LIBS     += \
+ VBoxClient_LIBS     += \
 	$(VBOX_LIB_VBGL_R3) \
 	$(PATH_STAGE_LIB)/additions/VBoxDnDGuestR3Lib$(VBOX_SUFF_LIB)
 endif
 
+ifdef VBOX_WITH_SEAMLESS
+ VBoxClient_DEFS    += VBOX_WITH_SEAMLESS
+ VBoxClient_SOURCES += \
+	seamless.cpp \
+	seamless-x11.cpp
+endif
+
+ifdef VBOX_WITH_VMSVGA
+ VBoxClient_DEFS    += VBOX_WITH_VMSVGA
+ VBoxClient_SOURCES += \
+	display-svga-x11.cpp
+endif
+
 ifdef VBOX_WITH_SHARED_CLIPBOARD
- VBoxClient_DEFS += \
+ VBoxClient_DEFS     += \
 	VBOX_WITH_SHARED_CLIPBOARD \
 	$(if $(VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS),VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS,)
- VBoxClient_SOURCES += \
+ VBoxClient_SOURCES  += \
 	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp \
 	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-x11.cpp \
@@ -172,4 +186,5 @@
           seamless.cpp \
           seamless-x11.cpp
+  tstSeamlessX11_DEFS   += VBOX_BUILD_TARGET=\"$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)\"
   tstSeamlessX11_LIBPATH = \
           $(VBOX_LIBPATH_X11)
Index: /trunk/src/VBox/Additions/x11/VBoxClient/VBoxClient.h
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/VBoxClient.h	(revision 86870)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/VBoxClient.h	(revision 86871)
@@ -30,55 +30,87 @@
 void VBClLogError(const char *pszFormat, ...);
 void VBClLogFatalError(const char *pszFormat, ...);
+void VBClLogVerbose(unsigned iLevel, const char *pszFormat, ...);
+
+int VBClLogCreate(const char *pszLogFile);
 void VBClLogDestroy(void);
-int VBClLogCreate(const char *pszLogFile);
 
 /** Call clean-up for the current service and exit. */
-extern void VBClCleanUp(bool fExit = true);
+extern void VBClShutdown(bool fExit = true);
 
-/** A simple interface describing a service.  VBoxClient will run exactly one
- * service per invocation. */
-struct VBCLSERVICE
+/**
+ * A service descriptor.
+ */
+typedef struct
 {
-    /** Returns the (friendly) name of the service. */
-    const char *(*getName)(void);
+    /** The short service name. 16 chars maximum (RTTHREAD_NAME_LEN). */
+    const char *pszName;
+    /** The longer service name. */
+    const char *pszDesc;
     /** Get the services default path to pidfile, relative to $HOME */
     /** @todo Should this also have a component relative to the X server number?
      */
-    const char *(*getPidFilePath)(void);
-    /** Special initialisation, if needed.  @a pause and @a resume are
-     * guaranteed not to be called until after this returns. */
-    int (*init)(struct VBCLSERVICE **ppInterface);
-    /** Run the service main loop */
-    int (*run)(struct VBCLSERVICE **ppInterface, bool fDaemonised);
-    /** Clean up any global resources before we shut down hard.  The last calls
-     * to @a pause and @a resume are guaranteed to finish before this is called.
+    const char *pszPidFilePath;
+    /** The usage options stuff for the --help screen. */
+    const char *pszUsage;
+    /** The option descriptions for the --help screen. */
+    const char *pszOptions;
+
+    /**
+     * Tries to parse the given command line option.
+     *
+     * @returns 0 if we parsed, -1 if it didn't and anything else means exit.
+     * @param   ppszShort   If not NULL it points to the short option iterator. a short argument.
+     *                      If NULL examine argv[*pi].
+     * @param   argc        The argument count.
+     * @param   argv        The argument vector.
+     * @param   pi          The argument vector index. Update if any value(s) are eaten.
      */
-    void (*cleanup)(struct VBCLSERVICE **ppInterface);
-};
+    DECLCALLBACKMEMBER(int, pfnOption,(const char **ppszShort, int argc, char **argv, int *pi));
 
-/** Default handler for various struct VBCLSERVICE member functions. */
-DECLINLINE(int) VBClServiceDefaultHandler(struct VBCLSERVICE **pSelf)
-{
-    RT_NOREF1(pSelf);
-    return VINF_SUCCESS;
-}
+    /**
+     * Called before parsing arguments.
+     * @returns VBox status code, or
+     *          VERR_NOT_AVAILABLE if service is supported on this platform in general but not available at the moment.
+     *          VERR_NOT_SUPPORTED if service is not supported on this platform. */
+    DECLCALLBACKMEMBER(int, pfnInit,(void));
 
-/** Default handler for the struct VBCLSERVICE clean-up member function.
- * Usually used because the service is cleaned up automatically when the user
- * process/X11 exits. */
-DECLINLINE(void) VBClServiceDefaultCleanup(struct VBCLSERVICE **ppInterface)
-{
-    RT_NOREF(ppInterface);
-}
+    /** Called from the worker thread.
+     *
+     * @returns VBox status code.
+     * @retval  VINF_SUCCESS if exitting because *pfShutdown was set.
+     * @param   pfShutdown      Pointer to a per service termination flag to check
+     *                          before and after blocking.
+     */
+    DECLCALLBACKMEMBER(int, pfnWorker,(bool volatile *pfShutdown));
 
-extern struct VBCLSERVICE **VBClGetClipboardService();
-extern struct VBCLSERVICE **VBClGetSeamlessService();
-extern struct VBCLSERVICE **VBClGetHostVersionService();
-#ifdef VBOX_WITH_DRAG_AND_DROP
-extern struct VBCLSERVICE **VBClGetDragAndDropService();
-#endif /* VBOX_WITH_DRAG_AND_DROP */
-extern struct VBCLSERVICE **VBClCheck3DService();
-extern struct VBCLSERVICE **VBClDisplaySVGAService();
-extern struct VBCLSERVICE **VBClDisplaySVGAX11Service();
+    /**
+     * Asks the service to stop.
+     *
+     * @remarks Will be called from the signal handler.
+     */
+    DECLCALLBACKMEMBER(void, pfnStop,(void));
+
+    /**
+     * Does termination cleanups.
+     *
+     * @remarks This will be called even if pfnInit hasn't been called or pfnStop failed!
+     */
+    DECLCALLBACKMEMBER(int, pfnTerm,(void));
+} VBCLSERVICE;
+/** Pointer to a VBCLSERVICE. */
+typedef VBCLSERVICE *PVBCLSERVICE;
+/** Pointer to a const VBCLSERVICE. */
+typedef VBCLSERVICE const *PCVBCLSERVICE;
+
+RT_C_DECLS_BEGIN
+extern VBCLSERVICE g_SvcClipboard;
+extern VBCLSERVICE g_SvcDisplayDRM;
+extern VBCLSERVICE g_SvcDisplaySVGA;
+extern VBCLSERVICE g_SvcDragAndDrop;
+extern VBCLSERVICE g_SvcHostVersion;
+extern VBCLSERVICE g_SvcSeamless;
+
+extern bool        g_fDaemonized;
+RT_C_DECLS_END
 
 #endif /* !GA_INCLUDED_SRC_x11_VBoxClient_VBoxClient_h */
Index: /trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp	(revision 86870)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp	(revision 86871)
@@ -58,5 +58,5 @@
 
 /**
- * Global clipboard context information.
+ * Struct keeping a Shared Clipboard context.
  */
 struct SHCLCONTEXT
@@ -75,5 +75,5 @@
 };
 
-/** Only one client is supported. There seems to be no need for more clients. */
+/** Only one context is supported at a time for now. */
 static SHCLCONTEXT g_Ctx;
 
@@ -258,6 +258,4 @@
 int vboxClipboardMain(void)
 {
-    LogRel(("Worker loop running\n"));
-
     int rc;
 
@@ -331,5 +329,5 @@
                 case VBGLR3CLIPBOARDEVENTTYPE_QUIT:
                 {
-                    LogRel2(("Host requested termination\n"));
+                    VBClLogVerbose(2, "Host requested termination\n");
                     fShutdown = true;
                     break;
@@ -368,6 +366,4 @@
     }
 
-    LogRel(("Worker loop ended\n"));
-
     LogFlowFuncLeaveRC(rc);
     return rc;
@@ -377,5 +373,5 @@
 static DECLCALLBACK(int) vboxClipoardFUSEThread(RTTHREAD hThreadSelf, void *pvUser)
 {
-    RT_NOREF(hThreadSelf, pvUser);
+    RT_NOREF(pvUser);
 
     VbglR3Init();
@@ -409,11 +405,11 @@
     }
     else
-        LogRel(("Error creating FUSE mount directory, rc=%Rrc\n", rc));
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-static int vboxClipboardFUSEStart()
+        VBClLogError("Error creating FUSE mount directory, rc=%Rrc\n", rc);
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+static int vboxClipboardFUSEStart(void)
 {
     LogFlowFuncEnter();
@@ -430,5 +426,5 @@
 }
 
-static int vboxClipboardFUSEStop()
+static int vboxClipboardFUSEStop(void)
 {
     LogFlowFuncEnter();
@@ -444,18 +440,7 @@
 #endif /* VBOX_WITH_SHARED_CLIPBOARD_FUSE */
 
-static const char *getName()
-{
-    return "Shared Clipboard";
-}
-
-static const char *getPidFilePath()
-{
-    return ".vboxclient-clipboard.pid";
-}
-
-static int init(struct VBCLSERVICE **pSelf)
-{
-    RT_NOREF(pSelf);
-
+/** @copydoc VBCLSERVICE::pfnInit */
+static int vbclShClInit(void)
+{
     int rc;
 
@@ -470,7 +455,8 @@
 }
 
-static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
-{
-    RT_NOREF(ppInterface, fDaemonised);
+/** @copydoc VBCLSERVICE::pfnWorker */
+static int vbclShClWorker(bool volatile *pfShutdown)
+{
+    RT_NOREF(pfShutdown);
 
     /* Initialise the guest library. */
@@ -483,4 +469,7 @@
         {
 #endif
+            /* Let the main thread know that it can continue spawning services. */
+            RTThreadUserSignal(RTThreadSelf());
+
             rc = vboxClipboardMain();
 
@@ -502,35 +491,35 @@
 }
 
-static void cleanup(struct VBCLSERVICE **ppInterface)
-{
-    RT_NOREF(ppInterface);
-
+/** @copydoc VBCLSERVICE::pfnStop */
+static void vbclShClStop(void)
+{
+    /* Disconnect from the host service.
+     * This will also send a VBOX_SHCL_HOST_MSG_QUIT from the host so that we can break out from our message worker. */
+    VbglR3ClipboardDisconnect(g_Ctx.CmdCtx.idClient);
+    g_Ctx.CmdCtx.idClient = 0;
+}
+
+/** @copydoc VBCLSERVICE::pfnTerm */
+static int vbclShClTerm(void)
+{
 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     ShClTransferCtxDestroy(&g_Ctx.TransferCtx);
 #endif
-}
-
-struct VBCLSERVICE vbclClipboardInterface =
-{
-    getName,
-    getPidFilePath,
-    init,
-    run,
-    cleanup
+
+    return VINF_SUCCESS;
+}
+
+VBCLSERVICE g_SvcClipboard =
+{
+    "shcl",                      /* szName */
+    "Shared Clipboard",          /* pszDescription */
+    ".vboxclient-clipboard.pid", /* pszPidFilePath */
+    NULL,                        /* pszUsage */
+    NULL,                        /* pszOptions */
+    NULL,                        /* pfnOption */
+    vbclShClInit,                /* pfnInit */
+    vbclShClWorker,              /* pfnWorker */
+    vbclShClStop,                /* pfnStop*/
+    vbclShClTerm                 /* pfnTerm */
 };
 
-struct CLIPBOARDSERVICE
-{
-    struct VBCLSERVICE *pInterface;
-};
-
-struct VBCLSERVICE **VBClGetClipboardService(void)
-{
-    struct CLIPBOARDSERVICE *pService =
-        (struct CLIPBOARDSERVICE *)RTMemAlloc(sizeof(*pService));
-
-    if (!pService)
-        VBClLogFatalError("Out of memory\n");
-    pService->pInterface = &vbclClipboardInterface;
-    return &pService->pInterface;
-}
Index: /trunk/src/VBox/Additions/x11/VBoxClient/display-svga-x11.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/display-svga-x11.cpp	(revision 86870)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/display-svga-x11.cpp	(revision 86871)
@@ -733,5 +733,5 @@
  * it (guest property) is set.
  */
-static bool checkDRMClient()
+static bool checkDRMClient(void)
 {
    uint32_t uGuestPropSvcClientID;
@@ -745,5 +745,5 @@
 }
 
-static bool startDRMClient()
+static bool startDRMClient(void)
 {
     char* argv[] = {NULL};
@@ -755,16 +755,24 @@
     int rc = execve(szDRMClientPath, argv, env);
     if (rc == -1)
-        VBClLogFatalError("execve for % returns the following error %d %s\n", szDRMClientPath, errno, strerror(errno));
+        VBClLogFatalError("execve for '%s' returns the following error %d: %s\n", szDRMClientPath, errno, strerror(errno));
     /* This is reached only when execve fails. */
     return false;
 }
 
-static bool init()
-{
+/** @copydoc VBCLSERVICE::pfnInit */
+static int vbclSVGAInit(void)
+{
+    /* In 32-bit guests GAs build on our release machines causes an xserver hang.
+     * So for 32-bit GAs we use our DRM client. */
+#if ARCH_BITS == 32
+    /* igore rc */ startDRMClient();
+    return VERR_NOT_AVAILABLE;
+#endif
+
     /* If DRM client is already running don't start this service. */
     if (checkDRMClient())
     {
         VBClLogFatalError("DRM resizing is already running. Exiting this service\n");
-        return false;
+        return VERR_NOT_AVAILABLE;
     }
     if (isXwayland())
@@ -781,5 +789,6 @@
 }
 
-static void cleanup()
+/** @copydoc VBCLSERVICE::pfnStop */
+static void vbclSVGAStop(void)
 {
     if (mpMonitorPositions)
@@ -788,5 +797,7 @@
         mpMonitorPositions = NULL;
     }
-    stopX11MonitorThread();
+
+    stopX11MonitorThread(); /** @todo r=andy We ignore rc!? */
+
     if (x11Context.pRandLibraryHandle)
     {
@@ -1331,27 +1342,7 @@
 }
 
-static const char *getName()
-{
-    return "Display SVGA X11";
-}
-
-static const char *getPidFilePath()
-{
-    return ".vboxclient-display-svga-x11.pid";
-}
-
-static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
-{
-    RT_NOREF(ppInterface, fDaemonised);
-
-    /* In 32-bit guests GAs build on our release machines causes an xserver hang.
-     * So for 32-bit GAs we use our DRM client. */
-#if ARCH_BITS == 32
-    startDRMClient();
-    return VERR_NOT_AVAILABLE;
-#endif
-
-    if (!init())
-        return VERR_NOT_AVAILABLE;
+static int vbclSVGAWorker(bool volatile *pfShutdown)
+{
+    RT_NOREF(pfShutdown);
 
     /* Do not acknowledge the first event we query for to pick up old events,
@@ -1369,4 +1360,8 @@
     if (rc == VERR_RESOURCE_BUSY)  /* Someone else has already acquired it. */
         return VERR_RESOURCE_BUSY;
+
+    /* Let the main thread know that it can continue spawning services. */
+    RTThreadUserSignal(RTThreadSelf());
+
     for (;;)
     {
@@ -1442,18 +1437,18 @@
             VBClLogFatalError("Failure waiting for event, rc=%Rrc\n", rc);
     }
-    cleanup();
-}
-
-static struct VBCLSERVICE interface =
-{
-    getName,
-    getPidFilePath,
-    VBClServiceDefaultHandler, /* Init */
-    run,
-    VBClServiceDefaultCleanup
-}, *pInterface = &interface;
-
-struct VBCLSERVICE **VBClDisplaySVGAX11Service()
-{
-    return &pInterface;
-}
+}
+
+VBCLSERVICE g_SvcDisplaySVGA =
+{
+    "dp-svga-x11",                      /* szName */
+    "SVGA X11 display",                 /* pszDescription */
+    ".vboxclient-display-svga-x11.pid", /* pszPidFilePath */
+    NULL,                               /* pszUsage */
+    NULL,                               /* pszOptions */
+    NULL,                               /* pfnOption */
+    vbclSVGAInit,                       /* pfnInit */
+    vbclSVGAWorker,                     /* pfnWorker */
+    vbclSVGAStop,                       /* pfnStop*/
+    NULL                                /* pfnTerm */
+};
+
Index: /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp	(revision 86870)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp	(revision 86871)
@@ -543,5 +543,6 @@
 
     int  init(uint32_t uScreenID);
-    void uninit(void);
+    int  term(void);
+    void stop(void);
     void reset(void);
 
@@ -666,7 +667,8 @@
     }
 
-    int init(void);
-    int run(bool fDaemonised = false);
-    void cleanup(void);
+    int  init(void);
+    int  worker(bool volatile *pfShutdown);
+    void stop(void);
+    int  term(void);
 
 private:
@@ -677,16 +679,19 @@
     /* Private member vars */
     Display             *m_pDisplay;
-
-    /** Our (thread-safe) event queue with
-     *  mixed events (DnD HGCM / X11). */
-    RTCMTList<DnDEvent>    m_eventQueue;
+    /** Our (thread-safe) event queue with mixed events (DnD HGCM / X11). */
+    RTCMTList<DnDEvent>  m_eventQueue;
     /** Critical section for providing serialized access to list
      *  event queue's contents. */
     RTCRITSECT           m_eventQueueCS;
+    /** Thread handle for the HGCM message pumping thread. */
     RTTHREAD             m_hHGCMThread;
+    /** Thread handle for the X11 message pumping thread. */
     RTTHREAD             m_hX11Thread;
     /** This service' DnD command context. */
     VBGLR3GUESTDNDCMDCTX m_dndCtx;
+    /** Event semaphore for new DnD events. */
     RTSEMEVENT           m_hEventSem;
+    /** Pointer to the allocated DnD instance.
+        Currently we only support and handle one instance at a time. */
     DragInstance        *m_pCurDnD;
     /** Stop indicator flag to signal the thread that it should shut down. */
@@ -694,5 +699,5 @@
 
     friend class DragInstance;
-};
+} g_Svc;
 
 /*********************************************************************************************************************************
@@ -715,7 +720,22 @@
 
 /**
- * Unitializes (destroys) this drag instance.
- */
-void DragInstance::uninit(void)
+ * Stops this drag instance.
+ */
+void DragInstance::stop(void)
+{
+    LogFlowFuncEnter();
+
+    int rc2 = VbglR3DnDDisconnect(&m_dndCtx);
+    AssertRC(rc2);
+
+    LogFlowFuncLeave();
+}
+
+/**
+ * Terminates (destroys) this drag instance.
+ *
+ * @return VBox status code.
+ */
+int DragInstance::term(void)
 {
     LogFlowFuncEnter();
@@ -724,17 +744,21 @@
         XDestroyWindow(m_pDisplay, m_wndProxy.hWnd);
 
-    int rc2 = VbglR3DnDDisconnect(&m_dndCtx);
+    int rc = VbglR3DnDDisconnect(&m_dndCtx);
+    AssertRCReturn(rc, rc);
 
     if (m_pvSelReqData)
         RTMemFree(m_pvSelReqData);
 
-    rc2 = RTSemEventDestroy(m_eventQueueEvent);
-    AssertRC(rc2);
-
-    rc2 = RTCritSectDelete(&m_eventQueueCS);
-    AssertRC(rc2);
-
-    rc2 = RTCritSectDelete(&m_dataCS);
-    AssertRC(rc2);
+    rc = RTSemEventDestroy(m_eventQueueEvent);
+    AssertRCReturn(rc, rc);
+
+    rc = RTCritSectDelete(&m_eventQueueCS);
+    AssertRCReturn(rc, rc);
+
+    rc = RTCritSectDelete(&m_dataCS);
+    AssertRCReturn(rc, rc);
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
 }
 
@@ -3067,9 +3091,5 @@
  ********************************************************************************************************************************/
 
-/**
- * Initializes the drag and drop service.
- *
- * @returns IPRT status code.
- */
+/** @copydoc VBCLSERVICE::pfnInit */
 int DragAndDropService::init(void)
 {
@@ -3106,5 +3126,5 @@
         AssertRCBreak(rc);
 
-        rc = RTThreadUserWait(m_hHGCMThread, 10 * 1000 /* 10s timeout */);
+        rc = RTThreadUserWait(m_hHGCMThread, RT_MS_30SEC);
         AssertRCBreak(rc);
 
@@ -3117,5 +3137,5 @@
         AssertRCBreak(rc);
 
-        rc = RTThreadUserWait(m_hX11Thread, 10 * 1000 /* 10s timeout */);
+        rc = RTThreadUserWait(m_hX11Thread, RT_MS_30SEC);
         AssertRCBreak(rc);
 
@@ -3135,17 +3155,7 @@
 }
 
-/**
- * Main loop for the drag and drop service which does the HGCM message
- * processing and routing to the according drag and drop instance(s).
- *
- * @returns IPRT status code.
- * @param   fDaemonised             Whether to run in daemonized or not. Does not
- *                                  apply for this service.
- */
-int DragAndDropService::run(bool fDaemonised /* = false */)
-{
-    RT_NOREF1(fDaemonised);
-    LogFlowThisFunc(("fDaemonised=%RTbool\n", fDaemonised));
-
+/** @copydoc VBCLSERVICE::pfnWorker */
+int DragAndDropService::worker(bool volatile *pfShutdown)
+{
     int rc;
     do
@@ -3167,11 +3177,11 @@
             if (RT_FAILURE(rc))
                 VBClLogError("Unable to connect to drag and drop service, rc=%Rrc\n", rc);
-            else if (rc == VINF_PERMISSION_DENIED)
-                VBClLogError("Not available on host, terminating\n");
+            else if (rc == VINF_PERMISSION_DENIED) /* No error, DnD might be just disabled. */
+                VBClLogInfo("Not available on host, terminating\n");
             break;
         }
 
-        VBClLogInfo("Started\n");
-        VBClLogInfo("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr());
+        /* Let the main thread know that it can continue spawning services. */
+        RTThreadUserSignal(RTThreadSelf());
 
         /* Enter the main event processing loop. */
@@ -3282,7 +3292,13 @@
                     }
 #endif
+                    case VBGLR3DNDEVENTTYPE_QUIT:
+                    {
+                        rc = VINF_SUCCESS;
+                        break;
+                    }
+
                     default:
                     {
-                       VBClLogError("Received unsupported message '%RU32'\n", pVbglR3Event->enmType);
+                        VBClLogError("Received unsupported message type %RU32\n", pVbglR3Event->enmType);
                         rc = VERR_NOT_SUPPORTED;
                         break;
@@ -3294,5 +3310,5 @@
                 {
                     /* Tell the user. */
-                   VBClLogError("Processing message %RU32 failed with %Rrc\n", pVbglR3Event->enmType, rc);
+                    VBClLogError("Processing message %RU32 failed with %Rrc\n", pVbglR3Event->enmType, rc);
 
                     /* If anything went wrong, do a reset and start over. */
@@ -3300,6 +3316,11 @@
                 }
 
+                const bool fQuit = pVbglR3Event->enmType == VBGLR3DNDEVENTTYPE_QUIT;
+
                 VbglR3DnDEventFree(e.hgcm);
                 e.hgcm = NULL;
+
+                if (fQuit)
+                    break;
             }
             else if (e.enmType == DnDEvent::DnDEventType_X11)
@@ -3317,7 +3338,8 @@
             XFlush(m_pDisplay);
 
-        } while (!ASMAtomicReadBool(&m_fStop));
-
-        VBClLogInfo("Stopped with rc=%Rrc\n", rc);
+            if (m_fStop)
+                break;
+
+        } while (!ASMAtomicReadBool(pfShutdown));
 
     } while (0);
@@ -3333,49 +3355,79 @@
 }
 
-void DragAndDropService::cleanup(void)
+/** @copydoc VBCLSERVICE::pfnStop */
+void DragAndDropService::stop(void)
 {
     LogFlowFuncEnter();
-
-    VBClLogInfo("Terminating ...\n");
 
     /* Set stop flag first. */
     ASMAtomicXchgBool(&m_fStop, true);
 
-    /* Disconnect from the HGCM host service, which in turn will make the HGCM thread stop. */
+    /* First, disconnect any instances. */
+    if (m_pCurDnD)
+        m_pCurDnD->stop();
+
+    /* Second, disconnect the service's DnD connection. */
     VbglR3DnDDisconnect(&m_dndCtx);
+
+    LogFlowFuncLeave();
+}
+
+/** @copydoc VBCLSERVICE::pfnTerm */
+int DragAndDropService::term(void)
+{
+    int rc = VINF_SUCCESS;
 
     /*
      * Wait for threads to terminate.
      */
-    int rcThread, rc2;
-    if (m_hHGCMThread != NIL_RTTHREAD)
-    {
-        VBClLogInfo("Terminating HGCM thread ...\n");
-
-        rc2 = RTThreadWait(m_hHGCMThread, 30 * 1000 /* 30s timeout */, &rcThread);
+    int rcThread;
+
+    if (m_hX11Thread != NIL_RTTHREAD)
+    {
+        VBClLogVerbose(2, "Terminating X11 thread ...\n");
+
+        int rc2 = RTThreadWait(m_hX11Thread, RT_MS_30SEC, &rcThread);
         if (RT_SUCCESS(rc2))
             rc2 = rcThread;
 
         if (RT_FAILURE(rc2))
-            VBClLogInfo("Error waiting for HGCM thread to terminate: %Rrc\n", rc2);
-    }
-
-    if (m_hX11Thread != NIL_RTTHREAD)
-    {
-        VBClLogInfo("Terminating X11 thread ...\n");
-
-        rc2 = RTThreadWait(m_hX11Thread, 200 /* 200ms timeout */, &rcThread);
+            VBClLogError("Error waiting for X11 thread to terminate: %Rrc\n", rc2);
+
+        if (RT_SUCCESS(rc))
+            rc = rc2;
+
+        m_hX11Thread = NIL_RTTHREAD;
+
+        VBClLogVerbose(2, "X11 thread terminated\n");
+    }
+
+    if (m_hHGCMThread != NIL_RTTHREAD)
+    {
+        VBClLogVerbose(2, "Terminating HGCM thread ...\n");
+
+        int rc2 = RTThreadWait(m_hHGCMThread, RT_MS_30SEC, &rcThread);
         if (RT_SUCCESS(rc2))
             rc2 = rcThread;
 
         if (RT_FAILURE(rc2))
-            VBClLogError("Error waiting for X11 thread to terminate: %Rrc\n", rc2);
-    }
-
-    VBClLogInfo("Terminating threads done\n");
+            VBClLogError("Error waiting for HGCM thread to terminate: %Rrc\n", rc2);
+
+        if (RT_SUCCESS(rc))
+            rc = rc2;
+
+        m_hHGCMThread = NIL_RTTHREAD;
+
+        VBClLogVerbose(2, "HGCM thread terminated\n");
+    }
+
+    if (m_pCurDnD)
+    {
+        delete m_pCurDnD;
+        m_pCurDnD = NULL;
+    }
 
     xHelpers::destroyInstance();
 
-    VbglR3Term();
+    return rc;
 }
 
@@ -3399,4 +3451,6 @@
     AssertRCReturn(rc, rc);
 
+    VBClLogVerbose(2, "HGCM thread started\n");
+
     /* Number of invalid messages skipped in a row. */
     int cMsgSkippedInvalid = 0;
@@ -3421,24 +3475,20 @@
         else
         {
-            if (rc == VERR_INTERRUPTED) /* Can happen due to disconnect, for instance. */
-                rc = VINF_SUCCESS;
-
-            if (RT_FAILURE(rc))
+            VBClLogError("Processing next message failed with rc=%Rrc\n", rc);
+
+            /* Old(er) hosts either are broken regarding DnD support or otherwise
+             * don't support the stuff we do on the guest side, so make sure we
+             * don't process invalid messages forever. */
+
+            if (cMsgSkippedInvalid++ > 32)
             {
-                VBClLogError("Processing next message failed with rc=%Rrc\n", rc);
-
-                /* Old(er) hosts either are broken regarding DnD support or otherwise
-                 * don't support the stuff we do on the guest side, so make sure we
-                 * don't process invalid messages forever. */
-
-                if (cMsgSkippedInvalid++ > 32)
-                {
-                    VBClLogError("Too many invalid/skipped messages from host, exiting ...\n");
-                    break;
-                }
+                VBClLogError("Too many invalid/skipped messages from host, exiting ...\n");
+                break;
             }
         }
 
     } while (!ASMAtomicReadBool(&pThis->m_fStop));
+
+    VBClLogVerbose(2, "HGCM thread ended\n");
 
     LogFlowFuncLeaveRC(rc);
@@ -3465,11 +3515,9 @@
     /* Note: Nothing to initialize here (yet). */
 
-    /* Set stop indicator on failure. */
-    if (RT_FAILURE(rc))
-        ASMAtomicXchgBool(&pThis->m_fStop, true);
-
     /* Let the service instance know in any case. */
     int rc2 = RTThreadUserSignal(hThread);
     AssertRC(rc2);
+
+    VBClLogVerbose(2, "X11 thread started\n");
 
     DnDEvent e;
@@ -3503,81 +3551,45 @@
     } while (!ASMAtomicReadBool(&pThis->m_fStop));
 
+    VBClLogVerbose(2, "X11 thread ended\n");
+
     LogFlowFuncLeaveRC(rc);
     return rc;
 }
-
-/** Drag and drop magic number, start of a UUID. */
-#define DRAGANDDROPSERVICE_MAGIC 0x67c97173
-
-/** VBoxClient service class wrapping the logic for the service while
- *  the main VBoxClient code provides the daemon logic needed by all services.
- */
-struct DRAGANDDROPSERVICE
-{
-    /** The service interface. */
-    struct VBCLSERVICE *pInterface;
-    /** Magic number for sanity checks. */
-    uint32_t uMagic;
-    /** Service object. */
-    DragAndDropService mDragAndDrop;
+/** @copydoc VBCLSERVICE::pfnInit */
+static int vbclDnDInit(void)
+{
+    return g_Svc.init();
+}
+
+/** @copydoc VBCLSERVICE::pfnWorker */
+static int vbclDnDWorker(bool volatile *pfShutdown)
+{
+    return g_Svc.worker(pfShutdown);
+}
+
+/** @copydoc VBCLSERVICE::pfnStop */
+static void vbclDnDStop(void)
+{
+    g_Svc.stop();
+}
+
+/** @copydoc VBCLSERVICE::pfnTerm */
+static int vbclDnDTerm(void)
+{
+    return g_Svc.term();
+}
+
+VBCLSERVICE g_SvcDragAndDrop =
+{
+    "dnd",                         /* szName */
+    "Drag'n'Drop",                 /* pszDescription */
+    ".vboxclient-draganddrop.pid", /* pszPidFilePath */
+    NULL,                          /* pszUsage */
+    NULL,                          /* pszOptions */
+    NULL,                          /* pfnOption */
+    vbclDnDInit,                   /* pfnInit */
+    vbclDnDWorker,                 /* pfnWorker */
+    vbclDnDStop,                   /* pfnStop*/
+    vbclDnDTerm                    /* pfnTerm */
 };
 
-static const char *getName()
-{
-    return "Drag and Drop (DnD)";
-}
-
-static const char *getPidFilePath()
-{
-    return ".vboxclient-draganddrop.pid";
-}
-
-static int init(struct VBCLSERVICE **ppInterface)
-{
-    struct DRAGANDDROPSERVICE *pSelf = (struct DRAGANDDROPSERVICE *)ppInterface;
-
-    if (pSelf->uMagic != DRAGANDDROPSERVICE_MAGIC)
-        VBClLogFatalError("Bad DnD service object!\n");
-    return pSelf->mDragAndDrop.init();
-}
-
-static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
-{
-    struct DRAGANDDROPSERVICE *pSelf = (struct DRAGANDDROPSERVICE *)ppInterface;
-
-    if (pSelf->uMagic != DRAGANDDROPSERVICE_MAGIC)
-        VBClLogFatalError("Bad DnD service object!\n");
-    return pSelf->mDragAndDrop.run(fDaemonised);
-}
-
-static void cleanup(struct VBCLSERVICE **ppInterface)
-{
-   struct DRAGANDDROPSERVICE *pSelf = (struct DRAGANDDROPSERVICE *)ppInterface;
-
-    if (pSelf->uMagic != DRAGANDDROPSERVICE_MAGIC)
-        VBClLogFatalError("Bad DnD service object!\n");
-    return pSelf->mDragAndDrop.cleanup();
-}
-
-struct VBCLSERVICE vbclDragAndDropInterface =
-{
-    getName,
-    getPidFilePath,
-    init,
-    run,
-    cleanup
-};
-
-/* Static factory. */
-struct VBCLSERVICE **VBClGetDragAndDropService(void)
-{
-    struct DRAGANDDROPSERVICE *pService =
-        (struct DRAGANDDROPSERVICE *)RTMemAlloc(sizeof(*pService));
-
-    if (!pService)
-        VBClLogFatalError("Out of memory\n");
-    pService->pInterface = &vbclDragAndDropInterface;
-    pService->uMagic = DRAGANDDROPSERVICE_MAGIC;
-    new(&pService->mDragAndDrop) DragAndDropService();
-    return &pService->pInterface;
-}
Index: /trunk/src/VBox/Additions/x11/VBoxClient/hostversion.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/hostversion.cpp	(revision 86870)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/hostversion.cpp	(revision 86871)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /** @file
- * X11 guest client - host version check.
+ * X11 guest client - Host version check.
  */
 
@@ -34,14 +34,4 @@
 #include "VBoxClient.h"
 
-static const char *getName()
-{
-    return "Host Version Check";
-}
-
-static const char *getPidFilePath()
-{
-    return ".vboxclient-hostversion.pid";
-}
-
 static int showNotify(const char *pszHeader, const char *pszBody)
 {
@@ -50,8 +40,8 @@
     DBusConnection *conn;
     DBusMessage* msg = NULL;
-    conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+    conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
     if (conn == NULL)
     {
-        LogRelFlowFunc(("Could not retrieve D-BUS session bus!\n"));
+        VBClLogError("Could not retrieve D-BUS session bus\n");
         rc = VERR_INVALID_HANDLE;
     }
@@ -127,18 +117,14 @@
 }
 
+/** @copydoc VBCLSERVICE::pfnWorker */
 /** @todo Move this part in VbglR3 and just provide a callback for the platform-specific
           notification stuff, since this is very similar to the VBoxTray code. */
-static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
+static int vbclHostVerWorker(bool volatile *pfShutdown)
 {
+    RT_NOREF(pfShutdown);
+
+    LogFlowFuncEnter();
+
     int rc;
-    LogFlowFunc(("\n"));
-
-    RT_NOREF(ppInterface);
-
-    /* Because we need desktop notifications to be displayed, wait
-     * some time to make the desktop environment load (as a work around). */
-    if (fDaemonised)
-        RTThreadSleep(30 * 1000 /* Wait 30 seconds */);
-
 # ifdef VBOX_WITH_DBUS
     rc = RTDBusLoadLib();
@@ -155,17 +141,25 @@
         rc = VbglR3GuestPropConnect(&uGuestPropSvcClientID);
         if (RT_FAILURE(rc))
-            VBClLogError("Cannot connect to guest property service while chcking for host version! rc = %Rrc\n", rc);
+            VBClLogError("Cannot connect to guest property service while chcking for host version, rc = %Rrc\n", rc);
     }
 
     if (RT_SUCCESS(rc))
     {
+        /* Let the main thread know that it can continue spawning services. */
+        RTThreadUserSignal(RTThreadSelf());
+
+        /* Because we need desktop notifications to be displayed, wait
+         * some time to make the desktop environment load (as a work around). */
+        if (g_fDaemonized)
+            RTThreadSleep(RT_MS_30SEC);
+
         char *pszHostVersion;
         char *pszGuestVersion;
-        bool bUpdate;
-
-        rc = VbglR3HostVersionCheckForUpdate(uGuestPropSvcClientID, &bUpdate, &pszHostVersion, &pszGuestVersion);
+        bool  fUpdate;
+
+        rc = VbglR3HostVersionCheckForUpdate(uGuestPropSvcClientID, &fUpdate, &pszHostVersion, &pszGuestVersion);
         if (RT_SUCCESS(rc))
         {
-            if (bUpdate)
+            if (fUpdate)
             {
                 char szMsg[1024];
@@ -198,32 +192,20 @@
     }
 # endif /* VBOX_WITH_GUEST_PROPS */
-    VbglR3Term();
-    LogFlowFunc(("returning %Rrc\n", rc));
+
     return rc;
 }
 
-struct VBCLSERVICE vbclHostVersionInterface =
+VBCLSERVICE g_SvcHostVersion =
 {
-    getName,
-    getPidFilePath,
-    VBClServiceDefaultHandler, /* init */
-    run,
-    VBClServiceDefaultCleanup
+    "hostversion",                   /* szName */
+    "VirtualBox host version check", /* pszDescription */
+    ".vboxclient-hostversion.pid",   /* pszPidFilePath */
+    NULL,                            /* pszUsage */
+    NULL,                            /* pszOptions */
+    NULL,                            /* pfnOption */
+    NULL,                            /* pfnInit */
+    vbclHostVerWorker,               /* pfnWorker */
+    NULL,                            /* pfnStop*/
+    NULL                             /* pfnTerm */
 };
 
-struct HOSTVERSIONSERVICE
-{
-    struct VBCLSERVICE *pInterface;
-};
-
-/* Static factory */
-struct VBCLSERVICE **VBClGetHostVersionService()
-{
-    struct HOSTVERSIONSERVICE *pService =
-        (struct HOSTVERSIONSERVICE *)RTMemAlloc(sizeof(*pService));
-
-    if (!pService)
-        VBClLogFatalError("Out of memory\n");
-    pService->pInterface = &vbclHostVersionInterface;
-    return &pService->pInterface;
-}
Index: /trunk/src/VBox/Additions/x11/VBoxClient/logging.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/logging.cpp	(revision 86870)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/logging.cpp	(revision 86871)
@@ -83,4 +83,19 @@
 
 /**
+ * Logs a verbose message.
+ *
+ * @param   pszFormat   The message text.
+ * @param   va          Format arguments.
+ */
+static void vbClLogV(const char *pszFormat, va_list va)
+{
+    char *psz = NULL;
+    RTStrAPrintfV(&psz, pszFormat, va);
+    AssertPtrReturnVoid(psz);
+    LogRel(("%s", psz));
+    RTStrFree(psz);
+}
+
+/**
  * Logs a fatal error, notifies the desktop environment via a message and
  * exits the application immediately.
@@ -97,7 +112,7 @@
     va_end(args);
 
-    AssertPtr(psz);
-    LogFlowFunc(("%s", psz));
-    LogRel(("%s", psz));
+    AssertPtrReturnVoid(psz);
+    LogFunc(("Fatal Error: %s", psz));
+    LogRel(("Fatal Error: %s", psz));
 
     vbclLogNotify(psz);
@@ -119,7 +134,7 @@
     va_end(args);
 
-    AssertPtr(psz);
-    LogFlowFunc(("%s", psz));
-    LogRel(("%s", psz));
+    AssertPtrReturnVoid(psz);
+    LogFunc(("Error: %s", psz));
+    LogRel(("Error: %s", psz));
 
     RTStrFree(psz);
@@ -135,13 +150,25 @@
     va_list args;
     va_start(args, pszFormat);
-    char *psz = NULL;
-    RTStrAPrintfV(&psz, pszFormat, args);
+    vbClLogV(pszFormat, args);
     va_end(args);
-
-    AssertPtr(psz);
-    LogFlowFunc(("%s", psz));
-    LogRel(("%s", psz));
-
-    RTStrFree(psz);
+}
+
+/**
+ * Displays a verbose message based on the currently
+ * set global verbosity level.
+ *
+ * @param   iLevel      Minimum log level required to display this message.
+ * @param   pszFormat   The message text.
+ * @param   ...         Format arguments.
+ */
+void VBClLogVerbose(unsigned iLevel, const char *pszFormat, ...)
+{
+    if (iLevel <= g_cVerbosity)
+    {
+        va_list va;
+        va_start(va, pszFormat);
+        vbClLogV(pszFormat, va);
+        va_end(va);
+    }
 }
 
@@ -265,5 +292,2 @@
 }
 
-void foo()
-{
-}
Index: /trunk/src/VBox/Additions/x11/VBoxClient/main.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/main.cpp	(revision 86870)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/main.cpp	(revision 86871)
@@ -27,4 +27,5 @@
 #include <iprt/buildconfig.h>
 #include <iprt/critsect.h>
+#include <iprt/errno.h>
 #include <iprt/getopt.h>
 #include <iprt/initterm.h>
@@ -34,4 +35,5 @@
 #include <VBox/VBoxGuestLib.h>
 #include <VBox/err.h>
+#include <VBox/version.h>
 #include "VBoxClient.h"
 
@@ -51,11 +53,40 @@
 
 /*********************************************************************************************************************************
+*   Local structures                                                                                                             *
+*********************************************************************************************************************************/
+/**
+ * The global service state.
+ */
+typedef struct VBCLSERVICESTATE
+{
+    /** Pointer to the service descriptor. */
+    PVBCLSERVICE    pDesc;
+    /** The worker thread. NIL_RTTHREAD if it's the main thread. */
+    RTTHREAD        Thread;
+    /** Whether Pre-init was called. */
+    bool            fPreInited;
+    /** Shutdown indicator. */
+    bool volatile   fShutdown;
+    /** Indicator set by the service thread exiting. */
+    bool volatile   fStopped;
+    /** Whether the service was started or not. */
+    bool            fStarted;
+} VBCLSERVICESTATE;
+/** Pointer to a service state. */
+typedef VBCLSERVICESTATE *PVBCLSERVICESTATE;
+
+
+/*********************************************************************************************************************************
 *   Global Variables                                                                                                             *
 *********************************************************************************************************************************/
-/*static int (*gpfnOldIOErrorHandler)(Display *) = NULL; - unused */
-
-/** Object representing the service we are running.  This has to be global
- * so that the cleanup routine can access it. */
-struct VBCLSERVICE **g_pService;
+/** The global service state. */
+VBCLSERVICESTATE     g_Service = { 0 };
+
+/** Set by the signal handler when being called. */
+static volatile bool g_fSignalHandlerCalled = false;
+/** Critical section for the signal handler. */
+static RTCRITSECT    g_csSignalHandler;
+/** Flag indicating Whether the service starts in daemonized  mode or not. */
+bool                 g_fDaemonized = false;
 /** The name of our pidfile.  It is global for the benefit of the cleanup
  * routine. */
@@ -70,16 +101,16 @@
 static RTCRITSECT    g_critSect;
 /** Counter of how often our daemon has been respawned. */
-unsigned      g_cRespawn = 0;
+unsigned             g_cRespawn = 0;
 /** Logging verbosity level. */
-unsigned      g_cVerbosity = 0;
+unsigned             g_cVerbosity = 0;
+/** Absolute path to log file, if any. */
 static char          g_szLogFile[RTPATH_MAX + 128] = "";
 
-
-/**
- * Clean up if we get a signal or something.
+/**
+ * Shut down if we get a signal or something.
  *
  * This is extern so that we can call it from other compilation units.
  */
-void VBClCleanUp(bool fExit /*=true*/)
+void VBClShutdown(bool fExit /*=true*/)
 {
     /* We never release this, as we end up with a call to exit(3) which is not
@@ -89,6 +120,7 @@
     if (RT_FAILURE(rc))
         VBClLogFatalError("Failure while acquiring the global critical section, rc=%Rrc\n", rc);
-    if (g_pService)
-        (*g_pService)->cleanup(g_pService);
+    if (   g_Service.pDesc
+        && g_Service.pDesc->pfnTerm)
+        g_Service.pDesc->pfnTerm();
     if (g_szPidFile[0] && g_hPidFile)
         VbglR3ClosePidFile(g_szPidFile, g_hPidFile);
@@ -98,15 +130,4 @@
     if (fExit)
         exit(RTEXITCODE_SUCCESS);
-}
-
-/**
- * A standard signal handler which cleans up and exits.
- */
-static void vboxClientSignalHandler(int cSignal)
-{
-    VBClLogInfo("Terminated with signal %d\n", cSignal);
-    /** Disable seamless mode */
-    VBClLogInfo("Terminating ...\n");
-    VBClCleanUp();
 }
 
@@ -130,18 +151,50 @@
 {
     RT_NOREF1(pDisplay);
-    VBClLogError("A fatal guest X Window error occurred.  This may just mean that the Window system was shut down while the client was still running\n");
-    VBClCleanUp();
+    VBClLogError("A fatal guest X Window error occurred. This may just mean that the Window system was shut down while the client was still running\n");
+    VBClShutdown();
     return 0;  /* We should never reach this. */
 }
 
 /**
- * Reset all standard termination signals to call our signal handler, which
- * cleans up and exits.
- */
-static void vboxClientSetSignalHandlers(void)
+ * A standard signal handler which cleans up and exits.
+ */
+static void vboxClientSignalHandler(int iSignal)
+{
+    int rc = RTCritSectEnter(&g_csSignalHandler);
+    if (RT_SUCCESS(rc))
+    {
+        if (g_fSignalHandlerCalled)
+        {
+            RTCritSectLeave(&g_csSignalHandler);
+            return;
+        }
+
+        VBClLogVerbose(2, "Received signal %d\n", iSignal);
+        g_fSignalHandlerCalled = true;
+
+        /* Leave critical section before stopping the service. */
+        RTCritSectLeave(&g_csSignalHandler);
+
+        if (   g_Service.pDesc
+            && g_Service.pDesc->pfnStop)
+        {
+            VBClLogVerbose(2, "Notifying service to stop ...\n");
+
+            /* Signal the service to stop. */
+            ASMAtomicWriteBool(&g_Service.fShutdown, true);
+
+            g_Service.pDesc->pfnStop();
+
+            VBClLogVerbose(2, "Service notified to stop, waiting on worker thread to stop ...\n");
+        }
+    }
+}
+
+/**
+ * Reset all standard termination signals to call our signal handler.
+ */
+static int vboxClientSignalHandlerInstall(void)
 {
     struct sigaction sigAction;
-
-    LogRelFlowFuncEnter();
     sigAction.sa_handler = vboxClientSignalHandler;
     sigemptyset(&sigAction.sa_mask);
@@ -155,5 +208,19 @@
     sigaction(SIGUSR1, &sigAction, NULL);
     sigaction(SIGUSR2, &sigAction, NULL);
-    LogRelFlowFuncLeave();
+
+    return RTCritSectInit(&g_csSignalHandler);
+}
+
+/**
+ * Uninstalls a previously installed signal handler.
+ */
+static int vboxClientSignalHandlerUninstall(void)
+{
+    signal(SIGTERM,  SIG_DFL);
+#ifdef SIGBREAK
+    signal(SIGBREAK, SIG_DFL);
+#endif
+
+    return RTCritSectDelete(&g_csSignalHandler);
 }
 
@@ -163,4 +230,10 @@
 static void vboxClientUsage(const char *pcszFileName)
 {
+    RTPrintf(VBOX_PRODUCT " VBoxClient "
+             VBOX_VERSION_STRING "\n"
+             "(C) 2005-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
+             "All rights reserved.\n"
+             "\n");
+
     RTPrintf("Usage: %s "
 #ifdef VBOX_WITH_SHARED_CLIPBOARD
@@ -170,11 +243,15 @@
              "--draganddrop|"
 #endif
-# ifdef VBOX_WITH_GUEST_PROPS
+#ifdef VBOX_WITH_GUEST_PROPS
              "--checkhostversion|"
 #endif
+#ifdef VBOX_WITH_SEAMLESS
              "--seamless|"
+#endif
+#ifdef VBOX_WITH_VMSVGA
              "--vmsvga"
-             "[-d|--nodaemon]\n", pcszFileName);
-    RTPrintf("Starts the VirtualBox DRM/X Window System guest services.\n\n");
+#endif
+             "\n[-d|--nodaemon]\n", pcszFileName);
+    RTPrintf("\n");
     RTPrintf("Options:\n");
 #ifdef VBOX_WITH_SHARED_CLIPBOARD
@@ -187,6 +264,10 @@
     RTPrintf("  --checkhostversion starts the host version notifier service\n");
 #endif
+#ifdef VBOX_WITH_SEAMLESS
     RTPrintf("  --seamless         starts the seamless windows service\n");
-    RTPrintf("  --vmsvga           starts VMSVGA dynamic resizing for x11/Wayland guests\n");
+#endif
+#ifdef VBOX_WITH_VMSVGA
+    RTPrintf("  --vmsvga           starts VMSVGA dynamic resizing for X11/Wayland guests\n");
+#endif
     RTPrintf("  -f, --foreground   run in the foreground (no daemonizing)\n");
     RTPrintf("  -d, --nodaemon     continues running as a system service\n");
@@ -209,10 +290,42 @@
 
 /**
+ * The service thread.
+ *
+ * @returns Whatever the worker function returns.
+ * @param   ThreadSelf      My thread handle.
+ * @param   pvUser          The service index.
+ */
+static DECLCALLBACK(int) vbclThread(RTTHREAD ThreadSelf, void *pvUser)
+{
+    PVBCLSERVICESTATE pState = (PVBCLSERVICESTATE)pvUser;
+    AssertPtrReturn(pState, VERR_INVALID_POINTER);
+
+#ifndef RT_OS_WINDOWS
+    /*
+     * Block all signals for this thread. Only the main thread will handle signals.
+     */
+    sigset_t signalMask;
+    sigfillset(&signalMask);
+    pthread_sigmask(SIG_BLOCK, &signalMask, NULL);
+#endif
+
+    AssertPtrReturn(pState->pDesc->pfnWorker, VERR_INVALID_POINTER);
+    int rc = pState->pDesc->pfnWorker(&pState->fShutdown);
+
+    VBClLogVerbose(2, "Worker loop ended with %Rrc\n", rc);
+
+    ASMAtomicXchgBool(&pState->fShutdown, true);
+    RTThreadUserSignal(ThreadSelf);
+    return rc;
+}
+
+/**
  * The main loop for the VBoxClient daemon.
- * @todo Clean up for readability.
  */
 int main(int argc, char *argv[])
 {
-    /* Initialise our runtime before all else. */
+    /* Note: No VBClLogXXX calls before actually creating the log. */
+
+    /* Initialize our runtime before all else. */
     int rc = RTR3InitExe(argc, &argv, 0);
     if (RT_FAILURE(rc))
@@ -222,5 +335,5 @@
      * object should probably never be used from multiple threads anyway. */
     if (!XInitThreads())
-        VBClLogFatalError("Failed to initialize X11 threads\n");
+        return RTMsgErrorExitFailure("Failed to initialize X11 threads\n");
 
     /* Get our file name for usage info and hints. */
@@ -241,5 +354,7 @@
 
         /* Services */
+#ifdef VBOX_WITH_GUEST_PROPS
         { "--checkhostversion",             VBOXCLIENT_OPT_CHECKHOSTVERSION,          RTGETOPT_REQ_NOTHING },
+#endif
 #ifdef VBOX_WITH_SHARED_CLIPBOARD
         { "--clipboard",                    VBOXCLIENT_OPT_CLIPBOARD,                 RTGETOPT_REQ_NOTHING },
@@ -248,6 +363,10 @@
         { "--draganddrop",                  VBOXCLIENT_OPT_DRAGANDDROP,               RTGETOPT_REQ_NOTHING },
 #endif
+#ifdef VBOX_WITH_SEAMLESS
         { "--seamless",                     VBOXCLIENT_OPT_SEAMLESS,                  RTGETOPT_REQ_NOTHING },
+#endif
+#ifdef VBOX_WITH_VMSVGA
         { "--vmsvga",                       VBOXCLIENT_OPT_VMSVGA,                    RTGETOPT_REQ_NOTHING },
+#endif
     };
 
@@ -256,4 +375,7 @@
     RTGETOPTSTATE           GetState;
     rc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0 /* fFlags */);
+    if (RT_FAILURE(rc))
+        return RTMsgErrorExitFailure("Failed to parse command line options, rc=%Rrc\n", rc);
+
     AssertRC(rc);
 
@@ -289,5 +411,5 @@
                 rc = RTStrCopy(g_szLogFile, sizeof(g_szLogFile), ValueUnion.psz);
                 if (RT_FAILURE(rc))
-                    VBClLogFatalError("Unable to create log file path, rc=%Rrc\n", rc);
+                    return RTMsgErrorExitFailure("Unable to set log file path, rc=%Rrc\n", rc);
                 break;
             }
@@ -295,5 +417,5 @@
             case 'n':
             {
-                fRespawn   = false;
+                fRespawn = false;
                 break;
             }
@@ -312,19 +434,19 @@
 
             /* Services */
-
+#ifdef VBOX_WITH_GUEST_PROPS
             case VBOXCLIENT_OPT_CHECKHOSTVERSION:
             {
-                if (g_pService)
+                if (g_Service.pDesc)
                     return vbclSyntaxOnlyOneService();
-                g_pService = VBClGetHostVersionService();
-                break;
-            }
-
+                g_Service.pDesc = &g_SvcHostVersion;
+                break;
+            }
+#endif
 #ifdef VBOX_WITH_SHARED_CLIPBOARD
             case VBOXCLIENT_OPT_CLIPBOARD:
             {
-                if (g_pService)
+                if (g_Service.pDesc)
                     return vbclSyntaxOnlyOneService();
-                g_pService = VBClGetClipboardService();
+                g_Service.pDesc = &g_SvcClipboard;
                 break;
             }
@@ -333,57 +455,67 @@
             case VBOXCLIENT_OPT_DRAGANDDROP:
             {
-                if (g_pService)
+                if (g_Service.pDesc)
                     return vbclSyntaxOnlyOneService();
-                g_pService = VBClGetDragAndDropService();
-                break;
-            }
-#endif
+                g_Service.pDesc = &g_SvcDragAndDrop;
+                break;
+            }
+#endif
+#ifdef VBOX_WITH_SEAMLESS
             case VBOXCLIENT_OPT_SEAMLESS:
             {
-                if (g_pService)
+                if (g_Service.pDesc)
                     return vbclSyntaxOnlyOneService();
-                g_pService = VBClGetSeamlessService();
-                break;
-            }
-
+                g_Service.pDesc = &g_SvcSeamless;
+                break;
+            }
+#endif
+#ifdef VBOX_WITH_VMSVGA
             case VBOXCLIENT_OPT_VMSVGA:
             {
-                if (g_pService)
+                if (g_Service.pDesc)
                     return vbclSyntaxOnlyOneService();
-                g_pService = VBClDisplaySVGAX11Service();
-                break;
-            }
+                g_Service.pDesc = &g_SvcDisplaySVGA;
+                break;
+            }
+#endif
+            case VINF_GETOPT_NOT_OPTION:
+                break;
 
             case VERR_GETOPT_UNKNOWN_OPTION:
-            {
-                RTMsgError("unrecognized option '%s'", ValueUnion.psz);
-                RTMsgInfo("Try '%s --help' for more information", pcszFileName);
-                return RTEXITCODE_SYNTAX;
-            }
-
-            case VINF_GETOPT_NOT_OPTION:
+                RT_FALL_THROUGH();
             default:
-                break;
+            {
+                if (   g_Service.pDesc
+                    && g_Service.pDesc->pfnOption)
+                {
+                    rc = g_Service.pDesc->pfnOption(NULL, argc, argv, &GetState.iNext);
+                }
+                else /* No service specified yet. */
+                    rc = VERR_NOT_FOUND;
+
+                if (RT_FAILURE(rc))
+                {
+                    RTMsgError("unrecognized option '%s'", ValueUnion.psz);
+                    RTMsgInfo("Try '%s --help' for more information", pcszFileName);
+                    return RTEXITCODE_SYNTAX;
+                }
+                break;
+            }
 
         } /* switch */
     } /* while RTGetOpt */
 
-    if (!g_pService)
-    {
-        RTMsgError("No service specified. Quitting because nothing to do!");
-        return RTEXITCODE_SYNTAX;
-    }
+    if (!g_Service.pDesc)
+        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No service specified. Quitting because nothing to do!");
 
     /* Initialize VbglR3 before we do anything else with the logger. */
     rc = VbglR3InitUser();
     if (RT_FAILURE(rc))
-        VBClLogFatalError("VbglR3InitUser failed: %Rrc", rc);
+        return RTMsgErrorExitFailure("VbglR3InitUser failed: %Rrc", rc);
 
     rc = VBClLogCreate(g_szLogFile[0] ? g_szLogFile : NULL);
     if (RT_FAILURE(rc))
-        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to create release log '%s', rc=%Rrc\n",
+        return RTMsgErrorExitFailure("Failed to create release log '%s', rc=%Rrc\n",
                               g_szLogFile[0] ? g_szLogFile : "<None>", rc);
-
-    LogRel(("Service: %s\n", (*g_pService)->getName()));
 
     if (!fDaemonise)
@@ -399,14 +531,16 @@
     }
 
+    VBClLogInfo("VBoxClient %s r%s started. Verbose level = %d\n", RTBldCfgVersion(), RTBldCfgRevisionStr(), g_cVerbosity);
+    VBClLogInfo("Service: %s\n", g_Service.pDesc->pszDesc);
+
     rc = RTCritSectInit(&g_critSect);
     if (RT_FAILURE(rc))
-        VBClLogFatalError("Initialising critical section failed: %Rrc\n", rc);
-    if ((*g_pService)->getPidFilePath)
+        VBClLogFatalError("Initializing critical section failed: %Rrc\n", rc);
+    if (g_Service.pDesc->pszPidFilePath)
     {
         rc = RTPathUserHome(g_szPidFile, sizeof(g_szPidFile));
         if (RT_FAILURE(rc))
-            VBClLogFatalError("Getting home directory for PID file failed: %Rrc\n", rc);
-        rc = RTPathAppend(g_szPidFile, sizeof(g_szPidFile),
-                          (*g_pService)->getPidFilePath());
+            VBClLogFatalError("Getting home directory failed: %Rrc\n", rc);
+        rc = RTPathAppend(g_szPidFile, sizeof(g_szPidFile), g_Service.pDesc->pszPidFilePath);
         if (RT_FAILURE(rc))
             VBClLogFatalError("Creating PID file path failed: %Rrc\n", rc);
@@ -414,5 +548,5 @@
             rc = VbglR3Daemonize(false /* fNoChDir */, false /* fNoClose */, fRespawn, &g_cRespawn);
         if (RT_FAILURE(rc))
-            VBClLogFatalError("Daemonizing failed: %Rrc\n", rc);
+            VBClLogFatalError("Daemonizing service failed: %Rrc\n", rc);
         if (g_szPidFile[0])
             rc = VbglR3PidFile(g_szPidFile, &g_hPidFile);
@@ -422,6 +556,5 @@
             VBClLogFatalError("Creating PID file failed: %Rrc\n", rc);
     }
-    /* Set signal handlers to clean up on exit. */
-    vboxClientSetSignalHandlers();
+
 #ifndef VBOXCLIENT_WITHOUT_X11
     /* Set an X11 error handler, so that we don't die when we get unavoidable
@@ -432,18 +565,104 @@
     XSetIOErrorHandler(vboxClientXLibIOErrorHandler);
 #endif
-    rc = (*g_pService)->init(g_pService);
+
+    bool fSignalHandlerInstalled = false;
     if (RT_SUCCESS(rc))
     {
-        rc = (*g_pService)->run(g_pService, fDaemonise);
+        rc = vboxClientSignalHandlerInstall();
+        if (RT_SUCCESS(rc))
+            fSignalHandlerInstalled = true;
+    }
+
+    if (   RT_SUCCESS(rc)
+        && g_Service.pDesc->pfnInit)
+    {
+        VBClLogInfo("Initializing service ...\n");
+        rc = g_Service.pDesc->pfnInit();
+    }
+
+    if (RT_SUCCESS(rc))
+    {
+        VBClLogInfo("Creating worker thread ...\n");
+        rc = RTThreadCreate(&g_Service.Thread, vbclThread, (void *)&g_Service, 0,
+                            RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, g_Service.pDesc->pszName);
         if (RT_FAILURE(rc))
-            VBClLogError("Running service failed: %Rrc\n", rc);
+        {
+            VBClLogError("Creating worker thread failed, rc=%Rrc\n", rc);
+        }
+        else
+        {
+            g_Service.fStarted = true;
+
+            /* Wait for the thread to initialize. */
+            /** @todo There is a race between waiting and checking
+             * the fShutdown flag of a thread here and processing
+             * the thread's actual worker loop. If the thread decides
+             * to exit the loop before we skipped the fShutdown check
+             * below the service will fail to start! */
+            /** @todo This presumably means either a one-shot service or that
+             * something has gone wrong.  In the second case treating it as failure
+             * to start is probably right, so we need a way to signal the first
+             * rather than leaving the idle thread hanging around.  A flag in the
+             * service description? */
+            RTThreadUserWait(g_Service.Thread, RT_MS_1MIN);
+            if (g_Service.fShutdown)
+            {
+                VBClLogError("Service failed to start!\n");
+                rc = VERR_GENERAL_FAILURE;
+            }
+            else
+            {
+                VBClLogInfo("Service started\n");
+
+                int rcThread;
+                rc = RTThreadWait(g_Service.Thread, RT_INDEFINITE_WAIT, &rcThread);
+                if (RT_SUCCESS(rc))
+                    rc = rcThread;
+
+                if (RT_FAILURE(rc))
+                    VBClLogError("Waiting on worker thread to stop failed, rc=%Rrc\n", rc);
+
+                if (g_Service.pDesc->pfnTerm)
+                {
+                    VBClLogInfo("Terminating service\n");
+
+                    int rc2 = g_Service.pDesc->pfnTerm();
+                    if (RT_SUCCESS(rc))
+                        rc = rc2;
+
+                    if (RT_SUCCESS(rc))
+                    {
+                        VBClLogInfo("Service terminated\n");
+                    }
+                    else
+                        VBClLogError("Service failed to terminate, rc=%Rrc\n", rc);
+                }
+            }
+        }
+    }
+
+    if (RT_FAILURE(rc))
+    {
+        if (rc == VERR_NOT_AVAILABLE)
+            VBClLogInfo("Service is not availabe, skipping\n");
+        else if (rc == VERR_NOT_SUPPORTED)
+            VBClLogInfo("Service is not supported on this platform, skipping\n");
+        else
+            VBClLogError("Service ended with error %Rrc\n", rc);
     }
     else
-    {
-        /** @todo r=andy Should we return an appropriate exit code if the service failed to init?
-         *               Must be tested carefully with our init scripts first. */
-        VBClLogError("Initializing service failed: %Rrc\n", rc);
-    }
-    VBClCleanUp(false /*fExit*/);
+        VBClLogVerbose(2, "Service ended\n");
+
+    if (fSignalHandlerInstalled)
+    {
+        int rc2 = vboxClientSignalHandlerUninstall();
+        AssertRC(rc2);
+    }
+
+    VBClShutdown(false /*fExit*/);
+
+    /** @todo r=andy Should we return an appropriate exit code if the service failed to init?
+     *               Must be tested carefully with our init scripts first. */
     return RTEXITCODE_SUCCESS;
 }
+
Index: /trunk/src/VBox/Additions/x11/VBoxClient/seamless.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/seamless.cpp	(revision 86870)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/seamless.cpp	(revision 86871)
@@ -22,22 +22,42 @@
 *   Header files                                                                                                                 *
 *********************************************************************************************************************************/
+#include <new>
+
 #include <X11/Xlib.h>
+
+#include <iprt/asm.h>
+#include <iprt/errcore.h>
+#include <iprt/mem.h>
 
 #include <VBox/log.h>
 #include <VBox/VBoxGuestLib.h>
-#include <iprt/errcore.h>
-#include <iprt/mem.h>
 
 #include "VBoxClient.h"
 #include "seamless.h"
 
-#include <new>
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+
+/**
+ * Struct for keeping a service instance.
+ */
+struct SEAMLESSSERVICE
+{
+    /** Seamless service object. */
+    SeamlessMain mSeamless;
+};
+
+/** Service instance data. */
+static SEAMLESSSERVICE g_Svc;
+
 
 SeamlessMain::SeamlessMain(void)
 {
-    LogRelFlowFuncEnter();
-    mX11MonitorThread = NIL_RTTHREAD;
+    mX11MonitorThread         = NIL_RTTHREAD;
     mX11MonitorThreadStopping = false;
-    mMode = VMMDev_Seamless_Disabled;
+
+    mMode    = VMMDev_Seamless_Disabled;
     mfPaused = true;
 }
@@ -45,6 +65,5 @@
 SeamlessMain::~SeamlessMain()
 {
-    LogRelFlowFuncEnter();
-    stop();
+    /* Stopping will be done via main.cpp. */
 }
 
@@ -54,17 +73,14 @@
 static void sendRegionUpdate(RTRECT *pRects, size_t cRects)
 {
-    LogRelFlowFuncEnter();
-    if (cRects && !pRects)  /* Assertion */
-    {
-        VBClLogError(("Region update called with NULL pointer!\n"));
+    if (   cRects
+        && !pRects)  /* Assertion */
+    {
+        VBClLogError(("Region update called with NULL pointer\n"));
         return;
     }
     VbglR3SeamlessSendRects(cRects, pRects);
-    LogRelFlowFuncLeave();
-}
-
-/**
- * initialise the service.
- */
+}
+
+/** @copydoc VBCLSERVICE::pfnInit */
 int SeamlessMain::init(void)
 {
@@ -72,6 +88,6 @@
     const char *pcszStage;
 
-    LogRelFlowFuncEnter();
-    do {
+    do
+    {
         pcszStage = "Connecting to the X server";
         rc = mX11Monitor.init(sendRegionUpdate);
@@ -89,47 +105,75 @@
         if (RT_FAILURE(rc))
             break;
+
     } while(0);
+
     if (RT_FAILURE(rc))
-        VBClLogError("Failed to start in stage '%s' -- error: %Rrc\n", pcszStage, rc);
-    return rc;
-}
-
-/**
- * Run the main service thread which listens for host state change
- * notifications.
- * @returns iprt status value.  Service will be set to the stopped state on
- *          failure.
- */
-int SeamlessMain::run(void)
+        VBClLogError("Failed to start in stage '%s' -- error %Rrc\n", pcszStage, rc);
+
+    return rc;
+}
+
+/** @copydoc VBCLSERVICE::pfnWorker */
+int SeamlessMain::worker(bool volatile *pfShutdown)
 {
     int rc = VINF_SUCCESS;
 
-    LogRelFlowFuncEnter();
+    /* Let the main thread know that it can continue spawning services. */
+    RTThreadUserSignal(RTThreadSelf());
+
     /* This will only exit if something goes wrong. */
-    while (RT_SUCCESS(rc) || rc == VERR_INTERRUPTED)
-    {
-        if (RT_FAILURE(rc))
-            /* If we are not stopping, sleep for a bit to avoid using up too
-                much CPU while retrying. */
-            RTThreadYield();
+    for (;;)
+    {
+        if (ASMAtomicReadBool(pfShutdown))
+            break;
+
         rc = nextStateChangeEvent();
-    }
-    if (RT_FAILURE(rc))
-    {
-        VBClLogError("Event loop failed with error: %Rrc\n", rc);
-        stop();
-    }
-    return rc;
-}
-
-/** Stops the service. */
-void SeamlessMain::stop()
-{
-    LogRelFlowFuncEnter();
+
+        if (rc == VERR_TRY_AGAIN)
+            rc = VINF_SUCCESS;
+
+        if (RT_FAILURE(rc))
+            break;
+
+        if (ASMAtomicReadBool(pfShutdown))
+            break;
+
+        /* If we are not stopping, sleep for a bit to avoid using up too
+           much CPU while retrying. */
+        RTThreadYield();
+    }
+
+    return rc;
+}
+
+/** @copydoc VBCLSERVICE::pfnStop */
+void SeamlessMain::stop(void)
+{
     VbglR3SeamlessSetCap(false);
     VbglR3CtlFilterMask(0, VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST);
     stopX11MonitorThread();
+}
+
+/** @copydoc VBCLSERVICE::pfnTerm */
+int SeamlessMain::term(void)
+{
+    int rc;
+
+    if (mX11MonitorThread)
+    {
+        rc = RTThreadWait(mX11MonitorThread, RT_MS_30SEC, NULL);
+        if (RT_SUCCESS(rc))
+        {
+            mX11MonitorThread = NIL_RTTHREAD;
+        }
+        else
+            VBClLogError("Failed to stop X11 monitor thread, rc=%Rrc\n", rc);
+    }
+    else
+        rc = VINF_SUCCESS;
+
     mX11Monitor.uninit();
-    LogRelFlowFuncLeave();
+
+    return rc;
 }
 
@@ -137,5 +181,7 @@
  * Waits for a seamless state change events from the host and dispatch it.
  *
- * @returns        IRPT return code.
+ * @returns VBox return code, or
+ *          VERR_TRY_AGAIN if no new status is available and we have to try it again
+ *          at some later point in time.
  */
 int SeamlessMain::nextStateChangeEvent(void)
@@ -143,5 +189,4 @@
     VMMDevSeamlessMode newMode = VMMDev_Seamless_Disabled;
 
-    LogRelFlowFuncEnter();
     int rc = VbglR3SeamlessWaitEvent(&newMode);
     if (RT_SUCCESS(rc))
@@ -151,22 +196,22 @@
         {
             case VMMDev_Seamless_Visible_Region:
-            /* A simplified seamless mode, obtained by making the host VM window
-             * borderless and making the guest desktop transparent. */
-                LogRelFlowFunc(("\"Visible region\" mode requested (VBoxClient)\n"));
+                /* A simplified seamless mode, obtained by making the host VM window
+                 * borderless and making the guest desktop transparent. */
+                VBClLogVerbose(2, "\"Visible region\" mode requested\n");
                 break;
             case VMMDev_Seamless_Disabled:
-                LogRelFlowFunc(("\"Disabled\" mode requested (VBoxClient)\n"));
+                VBClLogVerbose(2, "\"Disabled\" mode requested\n");
                 break;
             case VMMDev_Seamless_Host_Window:
-            /* One host window represents one guest window.  Not yet implemented. */
-                LogRelFunc(("Unsupported \"host window\" mode requested (VBoxClient)\n"));
+                /* One host window represents one guest window.  Not yet implemented. */
+                VBClLogVerbose(2, "Unsupported \"host window\" mode requested\n");
                 return VERR_NOT_SUPPORTED;
             default:
-                LogRelFunc(("Unsupported mode %d requested (VBoxClient)\n",
-                            newMode));
+                VBClLogError("Unsupported mode %d requested\n", newMode);
                 return VERR_NOT_SUPPORTED;
         }
     }
-    if (RT_SUCCESS(rc) || rc == VERR_TRY_AGAIN)
+    if (   RT_SUCCESS(rc)
+        || rc == VERR_TRY_AGAIN)
     {
         if (mMode == VMMDev_Seamless_Visible_Region)
@@ -177,8 +222,6 @@
     }
     else
-    {
-        LogRelFunc(("VbglR3SeamlessWaitEvent returned %Rrc (VBoxClient)\n", rc));
-    }
-    LogRelFlowFuncLeaveRC(rc);
+        VBClLogError("VbglR3SeamlessWaitEvent returned %Rrc\n", rc);
+
     return rc;
 }
@@ -189,23 +232,36 @@
 int SeamlessMain::x11MonitorThread(RTTHREAD hThreadSelf, void *pvUser)
 {
-    RT_NOREF1(hThreadSelf);
-    SeamlessMain *pHost = (SeamlessMain *)pvUser;
+    RT_NOREF(hThreadSelf);
+
+    SeamlessMain *pThis = (SeamlessMain *)pvUser;
+    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
+
     int rc = VINF_SUCCESS;
 
-    LogRelFlowFuncEnter();
-    while (!pHost->mX11MonitorThreadStopping)
-    {
-        if (!pHost->mfPaused)
+    RTThreadUserSignal(hThreadSelf);
+
+    VBClLogVerbose(2, "X11 monitor thread started\n");
+
+    while (!pThis->mX11MonitorThreadStopping)
+    {
+        if (!pThis->mfPaused)
         {
-            rc = pHost->mX11Monitor.start();
+            rc = pThis->mX11Monitor.start();
             if (RT_FAILURE(rc))
                 VBClLogFatalError("Failed to change the X11 seamless service state, mfPaused=%RTbool, rc=%Rrc\n",
-                                  pHost->mfPaused, rc);
+                                  pThis->mfPaused, rc);
         }
-        pHost->mX11Monitor.nextConfigurationEvent();
-        if (pHost->mfPaused || pHost->mX11MonitorThreadStopping)
-            pHost->mX11Monitor.stop();
-    }
-    LogRelFlowFuncLeaveRC(rc);
+
+        pThis->mX11Monitor.nextConfigurationEvent();
+
+        if (   pThis->mfPaused
+            || pThis->mX11MonitorThreadStopping)
+        {
+            pThis->mX11Monitor.stop();
+        }
+    }
+
+    VBClLogVerbose(2, "X11 monitor thread ended\n");
+
     return rc;
 }
@@ -216,129 +272,83 @@
 int SeamlessMain::startX11MonitorThread(void)
 {
-    int rc;
-
     mX11MonitorThreadStopping = false;
+
     if (isX11MonitorThreadRunning())
         return VINF_SUCCESS;
-    rc = RTThreadCreate(&mX11MonitorThread, x11MonitorThread, this, 0,
-                        RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
-                        "X11 events");
+
+    int rc = RTThreadCreate(&mX11MonitorThread, x11MonitorThread, this, 0,
+                            RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
+                            "seamless x11");
+    if (RT_SUCCESS(rc))
+        rc = RTThreadUserWait(mX11MonitorThread, RT_MS_30SEC);
+
     if (RT_FAILURE(rc))
-        LogRelFunc(("Warning: failed to start X11 monitor thread (VBoxClient)\n"));
-    return rc;
-}
-
-/**
- * Send a signal to the thread function that it should exit
+        VBClLogError("Failed to start X11 monitor thread, rc=%Rrc\n", rc);
+
+    return rc;
+}
+
+/**
+ * Stops the monitor thread.
  */
 int SeamlessMain::stopX11MonitorThread(void)
 {
-    int rc;
-
-    mX11MonitorThreadStopping = true;
     if (!isX11MonitorThreadRunning())
         return VINF_SUCCESS;
+
+    mX11MonitorThreadStopping = true;
     mX11Monitor.interruptEventWait();
-    rc = RTThreadWait(mX11MonitorThread, RT_INDEFINITE_WAIT, NULL);
+
+    int rcThread;
+    int rc = RTThreadWait(mX11MonitorThread, RT_MS_30SEC, &rcThread);
     if (RT_SUCCESS(rc))
+        rc = rcThread;
+
+    if (RT_SUCCESS(rc))
+    {
         mX11MonitorThread = NIL_RTTHREAD;
+    }
     else
-        LogRelThisFunc(("Failed to stop X11 monitor thread, rc=%Rrc!\n",
-                        rc));
-    return rc;
-}
-
-/** Service magic number, start of a UUID. */
-#define SEAMLESSSERVICE_MAGIC 0xd28ba727
-
-/** VBoxClient service class wrapping the logic for the seamless service while
- *  the main VBoxClient code provides the daemon logic needed by all services.
- */
-struct SEAMLESSSERVICE
-{
-    /** The service interface. */
-    struct VBCLSERVICE *pInterface;
-    /** Magic number for sanity checks. */
-    uint32_t magic;
-    /** Seamless service object. */
-    SeamlessMain mSeamless;
-    /** Are we initialised yet? */
-    bool mIsInitialised;
+        VBClLogError("Waiting for X11 monitor thread to stop failed, rc=%Rrc\n", rc);
+
+    return rc;
+}
+
+/** @copydoc VBCLSERVICE::pfnInit */
+static int vbclSeamlessInit(void)
+{
+    return g_Svc.mSeamless.init();
+}
+
+/** @copydoc VBCLSERVICE::pfnWorker */
+static int vbclSeamlessWorker(bool volatile *pfShutdown)
+{
+    return g_Svc.mSeamless.worker(pfShutdown);
+}
+
+/** @copydoc VBCLSERVICE::pfnStop */
+static void vbclSeamlessStop(void)
+{
+    return g_Svc.mSeamless.stop();
+}
+
+/** @copydoc VBCLSERVICE::pfnTerm */
+static int vbclSeamlessTerm(void)
+{
+    return g_Svc.mSeamless.term();
+}
+
+VBCLSERVICE g_SvcSeamless =
+{
+    "seamless",                 /* szName */
+    "Seamless Mode Support",    /* pszDescription */
+    ".vboxclient-seamless.pid", /* pszPidFilePath */
+    NULL,                       /* pszUsage */
+    NULL,                       /* pszOptions */
+    NULL,                       /* pfnOption */
+    vbclSeamlessInit,           /* pfnInit */
+    vbclSeamlessWorker,         /* pfnWorker */
+    vbclSeamlessStop,           /* pfnStop*/
+    vbclSeamlessTerm            /* pfnTerm */
 };
 
-static const char *getName()
-{
-    return "Seamless";
-}
-
-static const char *getPidFilePath(void)
-{
-    return ".vboxclient-seamless.pid";
-}
-
-static struct SEAMLESSSERVICE *getClassFromInterface(struct VBCLSERVICE **
-                                                         ppInterface)
-{
-    struct SEAMLESSSERVICE *pSelf = (struct SEAMLESSSERVICE *)ppInterface;
-    if (pSelf->magic != SEAMLESSSERVICE_MAGIC)
-        VBClLogFatalError("Bad seamless service object!\n");
-    return pSelf;
-}
-
-static int init(struct VBCLSERVICE **ppInterface)
-{
-    struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface);
-
-    if (pSelf->mIsInitialised)
-        return VERR_INTERNAL_ERROR;
-
-    int rc = pSelf->mSeamless.init();
-    if (RT_FAILURE(rc))
-        return rc;
-    pSelf->mIsInitialised = true;
-    return VINF_SUCCESS;
-}
-
-static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
-{
-    RT_NOREF1(fDaemonised);
-    struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface);
-    int rc;
-
-    if (!pSelf->mIsInitialised)
-        return VERR_INTERNAL_ERROR;
-    /* This only exits on error. */
-    rc = pSelf->mSeamless.run();
-    pSelf->mIsInitialised = false;
-    return rc;
-}
-
-static void cleanup(struct VBCLSERVICE **ppInterface)
-{
-    RT_NOREF(ppInterface);
-    VbglR3SeamlessSetCap(false);
-    VbglR3Term();
-}
-
-struct VBCLSERVICE vbclSeamlessInterface =
-{
-    getName,
-    getPidFilePath,
-    init,
-    run,
-    cleanup
-};
-
-struct VBCLSERVICE **VBClGetSeamlessService()
-{
-    struct SEAMLESSSERVICE *pService =
-        (struct SEAMLESSSERVICE *)RTMemAlloc(sizeof(*pService));
-
-    if (!pService)
-        VBClLogFatalError("Out of memory\n");
-    pService->pInterface = &vbclSeamlessInterface;
-    pService->magic = SEAMLESSSERVICE_MAGIC;
-    new(&pService->mSeamless) SeamlessMain();
-    pService->mIsInitialised = false;
-    return &pService->pInterface;
-}
Index: /trunk/src/VBox/Additions/x11/VBoxClient/seamless.h
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/seamless.h	(revision 86870)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/seamless.h	(revision 86871)
@@ -84,32 +84,15 @@
 #endif
 
-    /**
-      * Initialise the service.
-      */
+    /** @copydoc VBCLSERVICE::pfnInit */
     int init(void);
 
-    /**
-      * Run the service.
-      * @returns iprt status value
-      */
-    int run(void);
+    /** @copydoc VBCLSERVICE::pfnWorker */
+    int worker(bool volatile *pfShutdown);
 
-    /**
-     * Stops the service.
-     */
-    void stop();
+    /** @copydoc VBCLSERVICE::pfnStop */
+    void stop(void);
 
-    /** Pause the service loop.  This must be safe to call on a different thread
-     * and potentially before @a run is or after it exits.
-     * This is called by the VT monitoring thread to allow the service to disable
-     * itself when the X server is switched out.  If the monitoring functionality
-     * is available then @a pause or @a resume will be called as soon as it starts
-     * up. */
-    int pause();
-    /** Resume after pausing.  The same applies here as for @a pause. */
-    int resume();
-
-    /** Run a few tests to be sure everything is working as intended. */
-    int selfTest();
+    /** @copydoc VBCLSERVICE::pfnTerm */
+    int term(void);
 };
 
Index: /trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp	(revision 86870)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp	(revision 86871)
@@ -58,4 +58,14 @@
 
     exit(1);
+}
+
+void VBClLogVerbose(unsigned iLevel, const char *pszFormat, ...)
+{
+    RT_NOREF(iLevel);
+
+    va_list va;
+    va_start(va, pszFormat);
+    RTPrintf("%s", pszFormat);
+    va_end(va);
 }
 
@@ -156,5 +166,6 @@
         RTPrintf("Failed to initialise seamless Additions, rc = %Rrc\n", rc);
     }
-    rc = seamless.run();
+    bool fShutdown = false;
+    rc = seamless.worker(&fShutdown);
     if (rc != VINF_SUCCESS)
     {
