main.cpp revision 3805ecaf5329df050ede4219a59098e756590e4d
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** @file
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync * VirtualBox Guest Service:
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync * Linux guest.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/*
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Copyright (C) 2006-2011 Oracle Corporation
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync *
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * available from http://www.virtualbox.org. This file is free software;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * General Public License (GPL) as published by the Free Software
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <sys/types.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <stdlib.h> /* For exit */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <stdio.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <string.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <unistd.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <errno.h>
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync#include <poll.h>
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync#include <signal.h>
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <X11/Xlib.h>
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync#include <X11/Xatom.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync#include <iprt/critsect.h>
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync#include <iprt/env.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/file.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/initterm.h>
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync#include <iprt/message.h>
b450d7a1747c5f4fb7c917a8ec1f9ce8440d7ffevboxsync#include <iprt/path.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/param.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/stream.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/string.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <iprt/types.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <VBox/VBoxGuestLib.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include <VBox/log.h>
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#include "VBoxClient.h"
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int (*gpfnOldIOErrorHandler)(Display *) = NULL;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** Object representing the service we are running. This has to be global
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * so that the cleanup routine can access it. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncVBoxClient::Service *g_pService;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** The name of our pidfile. It is global for the benefit of the cleanup
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * routine. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic char g_szPidFile[RTPATH_MAX];
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** The file handle of our pidfile. It is global for the benefit of the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * cleanup routine. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic RTFILE g_hPidFile;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** Global critical section held during the clean-up routine (to prevent it
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * being called on multiple threads at once) or things which may not happen
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * during clean-up (e.g. pausing and resuming the service).
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncRTCRITSECT g_critSect;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** Clean up if we get a signal or something. This is extern so that we
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * can call it from other compilation units. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncvoid VBoxClient::CleanUp()
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* We never release this, as we end up with a call to exit(3) which is not
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * async-safe. Unless we fix this application properly, we should be sure
6a795f9e75e30c7f1d75cd45e5de233c71662f58vboxsync * never to exit from anywhere except from this method. */
6a795f9e75e30c7f1d75cd45e5de233c71662f58vboxsync int rc = RTCritSectEnter(&g_critSect);
6a795f9e75e30c7f1d75cd45e5de233c71662f58vboxsync if (RT_FAILURE(rc))
6a795f9e75e30c7f1d75cd45e5de233c71662f58vboxsync {
6a795f9e75e30c7f1d75cd45e5de233c71662f58vboxsync LogRel(("VBoxClient: Failure while acquiring the global critical section, rc=%Rrc\n", rc));
6a795f9e75e30c7f1d75cd45e5de233c71662f58vboxsync abort();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (g_pService)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_pService->cleanup();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (g_szPidFile[0] && g_hPidFile)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync VbglR3ClosePidFile(g_szPidFile, g_hPidFile);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync VbglR3Term();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync exit(0);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * A standard signal handler which cleans up and exits.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncvoid vboxClientSignalHandler(int cSignal)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogRel(("VBoxClient: terminated with signal %d\n", cSignal));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** Disable seamless mode */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf(("VBoxClient: terminating...\n"));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync VBoxClient::CleanUp();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Xlib error handler for certain errors that we can't avoid.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncint vboxClientXLibErrorHandler(Display *pDisplay, XErrorEvent *pError)
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync{
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync char errorText[1024];
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync XGetErrorText(pDisplay, pError->error_code, errorText, sizeof(errorText));
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync LogRelFlow(("VBoxClient: an X Window protocol error occurred: %s (error code %d). Request code: %d, minor code: %d, serial number: %d\n", errorText, pError->error_code, pError->request_code, pError->minor_code, pError->serial));
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync return 0; /* We should never reach this. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Xlib error handler for fatal errors. This often means that the programme is still running
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * when X exits.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int vboxClientXLibIOErrorHandler(Display *pDisplay)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogRel(("VBoxClient: 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"));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync VBoxClient::CleanUp();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return 0; /* We should never reach this. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Reset all standard termination signals to call our signal handler, which
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * cleans up and exits.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncvoid vboxClientSetSignalHandlers(void)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync struct sigaction sigAction;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogRelFlowFunc(("\n"));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync sigAction.sa_handler = vboxClientSignalHandler;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync sigemptyset(&sigAction.sa_mask);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync sigAction.sa_flags = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync sigaction(SIGHUP, &sigAction, NULL);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync sigaction(SIGINT, &sigAction, NULL);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync sigaction(SIGQUIT, &sigAction, NULL);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync sigaction(SIGPIPE, &sigAction, NULL);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync sigaction(SIGALRM, &sigAction, NULL);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync sigaction(SIGTERM, &sigAction, NULL);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync sigaction(SIGUSR1, &sigAction, NULL);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync sigaction(SIGUSR2, &sigAction, NULL);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogRelFlowFunc(("returning\n"));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** Connect to the X server and return the "XFree86_VT" root window property,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * or 0 on failure. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic unsigned long getXOrgVT(Display *pDisplay)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync Atom actualType;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int actualFormat;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync unsigned long cItems, cbLeft, cVT = 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync unsigned long *pValue;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync XGetWindowProperty(pDisplay, DefaultRootWindow(pDisplay),
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync XInternAtom(pDisplay, "XFree86_VT", False), 0, 1, False,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync XA_INTEGER, &actualType, &actualFormat, &cItems, &cbLeft,
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync (unsigned char **)&pValue);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (cItems && actualFormat == 32)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync cVT = *pValue;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync XFree(pValue);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return cVT;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** Check whether the current virtual terminal is the one running the X server.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic void checkVTSysfs(RTFILE hFile, uint32_t cVT)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync char szTTY[7] = "";
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync uint32_t cTTY;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync size_t cbRead;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync const char *pcszStage;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync do {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszStage = "reading /sys/class/tty/tty0/active";
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTFileReadAt(hFile, 0, (void *)szTTY, sizeof(szTTY), &cbRead);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync szTTY[cbRead - 1] = '\0';
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszStage = "getting VT number from sysfs file";
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTStrToUInt32Full(&szTTY[3], 10, &cTTY);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszStage = "entering critical section";
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectEnter(&g_critSect);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszStage = "asking service to pause or resume";
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (cTTY == cVT)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = g_pService->resume();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = g_pService->pause();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszStage = "leaving critical section";
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectLeave(&g_critSect);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync } while(false);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogRelFunc(("VBoxClient: failed at stage: \"%s\" rc: %Rrc cVT: %d szTTY: %s.\n",
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszStage, rc, (int) cVT, szTTY));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RTCritSectIsOwner(&g_critSect))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTCritSectLeave(&g_critSect);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync VBoxClient::CleanUp();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/** Poll for TTY changes using sysfs and for X server disconnection.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Reading from the start of the pollable file "/sys/class/tty/tty0/active"
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * returns the currently active TTY as a string of the form "tty<n>", with n
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * greater than zero. Polling for POLLPRI returns when the TTY changes.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @a cVT should be zero if we do not know the X server's VT. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic void pollTTYAndXServer(Display *pDisplay, uint32_t cVT)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTFILE hFile = NIL_RTFILE;
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync struct pollfd pollFD[2];
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync unsigned cPollFD = 1;
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync int rc;
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync pollFD[1].fd = -1;
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync pollFD[1].revents = 0;
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync /* This block could be Linux-only, but keeping it on Solaris too, where it
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync * should just fail gracefully, gives us more code path coverage. */
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync if (cVT)
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync {
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync rc = RTFileOpen(&hFile, "/sys/class/tty/tty0/active",
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_SUCCESS(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pollFD[1].fd = RTFileToNative(hFile);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pollFD[1].events = POLLPRI;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync cPollFD = 2;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync AssertRelease(pollFD[1].fd >= 0 || cPollFD == 1);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pollFD[0].fd = ConnectionNumber(pDisplay);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pollFD[0].events = POLLIN;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync while (true)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (hFile != NIL_RTFILE)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync checkVTSysfs(hFile, cVT);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* The only point of this loop is to trigger the I/O error handler if
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * appropriate. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync while (XPending(pDisplay))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync XEvent ev;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync XNextEvent(pDisplay, &ev);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* If we get caught in a tight loop for some reason try to limit the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * damage. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (poll(pollFD, cPollFD, 0) > 0)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogRel(("Monitor thread: unexpectedly fast event, revents=0x%x, 0x%x.\n",
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pollFD[0].revents, pollFD[1].revents));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTThreadYield();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync if ( (poll(pollFD, cPollFD, -1) < 0 && errno != EINTR)
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync || pollFD[0].revents & POLLNVAL
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync || pollFD[1].revents & POLLNVAL)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync LogRel(("Monitor thread: poll failed, stopping.\n"));
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync VBoxClient::CleanUp();
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync }
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync }
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Thread which notifies the service when we switch to a different VT or back
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * and cleans up when the X server exits.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @note runs until programme exit.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncstatic int pfnMonitorThread(RTTHREAD self, void *pvUser)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync Display *pDisplay;
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync unsigned long cVT;
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync RTFILE hFile;
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync
4946f90c5c7016131555f0c925091d4ede6bdde0vboxsync pDisplay = XOpenDisplay(NULL);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!pDisplay)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync cVT = getXOrgVT(pDisplay);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Note: cVT will be 0 if we failed to get it. This is valid. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pollTTYAndXServer(pDisplay, (uint32_t) cVT);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Should never get here. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Start the thread which notifies the service when we switch to a different
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * VT or back, and terminates us when the X server exits. The first is best
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * effort functionality: XFree86 4.3 and older do not report their VT via the
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * "XFree86_VT" root window property at all, and pre-2.6.38 Linux does not
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * provide the interface in "sysfs" which we use. If there is a need for this
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * to work with pre-2.6.38 Linux we can send the VT_GETSTATE ioctl to
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync * /dev/console at regular intervals.
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync */
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsyncstatic int startMonitorThread()
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync{
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync return RTThreadCreate(NULL, pfnMonitorThread, NULL, 0,
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync RTTHREADTYPE_INFREQUENT_POLLER, 0, "MONITOR");
ee4d840f54fd2dcea8a73b1b86d5ec0db370b05dvboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * Print out a usage message and exit with success.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncvoid vboxClientUsage(const char *pcszFileName)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf("Usage: %s --clipboard|"
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#ifdef VBOX_WITH_DRAG_AND_DROP
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync "--draganddrop|"
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#endif
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync "--display|"
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync# ifdef VBOX_WITH_GUEST_PROPS
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync "--checkhostversion|"
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#endif
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync "--seamless [-d|--nodaemon]\n", pcszFileName);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf("Start the VirtualBox X Window System guest services.\n\n");
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf("Options:\n");
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf(" --clipboard start the shared clipboard service\n");
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#ifdef VBOX_WITH_DRAG_AND_DROP
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf(" --draganddrop start the drag and drop service\n");
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#endif
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf(" --display start the display management service\n");
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#ifdef VBOX_WITH_GUEST_PROPS
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf(" --checkhostversion start the host version notifier service\n");
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#endif
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf(" --seamless start the seamless windows service\n");
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf(" -d, --nodaemon continue running as a system service\n");
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf("\n");
23631945c9cb3df68ca51c69ed0b77e90164b402vboxsync exit(0);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync/**
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * The main loop for the VBoxClient daemon.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * @todo Clean up for readability.
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsyncint main(int argc, char *argv[])
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync{
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync bool fDaemonise = true;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync int rc;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync const char *pcszFileName, *pcszStage;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Initialise our runtime before all else. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTR3InitExe(argc, &argv, 0);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return RTMsgInitFailure(rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* This should never be called twice in one process - in fact one Display
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * object should probably never be used from multiple threads anyway. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!XInitThreads())
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return 1;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Get our file name for error output. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszFileName = RTPathFilename(argv[0]);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!pcszFileName)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszFileName = "VBoxClient";
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Initialise the guest library. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VbglR3InitUser();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf("%s: failed to connect to the VirtualBox kernel service, rc=%Rrc\n",
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszFileName, rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return 1;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Parse our option(s) */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /** @todo Use RTGetOpt() if the arguments become more complex. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync for (int i = 1; i < argc; ++i)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VERR_INVALID_PARAMETER;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--nodaemon"))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* If the user is running in "no daemon" mode anyway, send critical
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * logging to stdout as well. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync PRTLOGGER pReleaseLog = RTLogRelDefaultInstance();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pReleaseLog)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTLogDestinations(pReleaseLog, "stdout");
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (pReleaseLog && RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf("%s: failed to redivert error output, rc=%Rrc\n",
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszFileName, rc);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync fDaemonise = false;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else if (!strcmp(argv[i], "--clipboard"))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (g_pService)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_pService = VBoxClient::GetClipboardService();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else if (!strcmp(argv[i], "--display"))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (g_pService)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_pService = VBoxClient::GetDisplayService();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else if (!strcmp(argv[i], "--seamless"))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (g_pService)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_pService = VBoxClient::GetSeamlessService();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else if (!strcmp(argv[i], "--checkhostversion"))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (g_pService)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_pService = VBoxClient::GetHostVersionService();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#ifdef VBOX_WITH_DRAG_AND_DROP
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else if (!strcmp(argv[i], "--draganddrop"))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (g_pService)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_pService = VBoxClient::GetDragAndDropService();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync#endif /* VBOX_WITH_DRAG_AND_DROP */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync vboxClientUsage(pcszFileName);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return 0;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf("%s: unrecognized option `%s'\n", pcszFileName, argv[i]);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync RTPrintf("Try `%s --help' for more information\n", pcszFileName);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return 1;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VINF_SUCCESS;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc) || !g_pService)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync vboxClientUsage(pcszFileName);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return 1;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync do {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszStage = "Initialising critical section";
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTCritSectInit(&g_critSect);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszStage = "Getting home directory for pid-file";
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTPathUserHome(g_szPidFile, sizeof(g_szPidFile));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszStage = "Creating pid-file path";
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = RTPathAppend(g_szPidFile, sizeof(g_szPidFile),
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_pService->getPidFilePath());
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszStage = "Daemonising";
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (fDaemonise)
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = VbglR3Daemonize(false /* fNoChDir */, false /* fNoClose */);
493189f09538207d222d646e7ddc76adb3c438eevboxsync if (RT_FAILURE(rc))
493189f09538207d222d646e7ddc76adb3c438eevboxsync break;
493189f09538207d222d646e7ddc76adb3c438eevboxsync pcszStage = "Creating pid-file";
493189f09538207d222d646e7ddc76adb3c438eevboxsync if (g_szPidFile[0])
493189f09538207d222d646e7ddc76adb3c438eevboxsync rc = VbglR3PidFile(g_szPidFile, &g_hPidFile);
75ef08b33f9c67a8dd50748ece1117aed8098d51vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync break;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Set signal handlers to clean up on exit. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync vboxClientSetSignalHandlers();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Set an X11 error handler, so that we don't die when we get unavoidable
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * errors. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync XSetErrorHandler(vboxClientXLibErrorHandler);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync /* Set an X11 I/O error handler, so that we can shutdown properly on
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync * fatal errors. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync XSetIOErrorHandler(vboxClientXLibIOErrorHandler);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszStage = "Initialising service";
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = g_pService->init();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync } while (0);
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync {
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogRelFunc(("VBoxClient: failed at stage: \"%s\" rc: %Rrc\n",
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync pcszStage, rc));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync VbglR3Term();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return 1;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync }
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc = startMonitorThread();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync if (RT_FAILURE(rc))
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync LogRel(("Failed to start the monitor thread (%Rrc). Exiting.\n",
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync rc));
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync else
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync g_pService->run(fDaemonise); /* Should never return. */
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync VBoxClient::CleanUp();
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync return 1;
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync}
9dca051a5f8ff457ef1692990f6ecfa280daf265vboxsync