VirtualBox

Ignore:
Timestamp:
Mar 26, 2009 11:46:38 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
45146
Message:

Additions/x11/VBoxClient: run a separate process for each service and create pidfiles to ensure uniqueness

Location:
trunk/src/VBox/Additions/x11/VBoxClient
Files:
3 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/x11/VBoxClient/Makefile.kmk

    r16014 r18360  
    5252 VBoxClient_DEFS += SEAMLESS_GUEST DYNAMIC_RESIZE
    5353 VBoxClient_SOURCES += \
     54        seamless.cpp \
    5455        seamless-host.cpp \
    5556        seamless-x11.cpp \
    5657        thread.cpp \
    57         displaychange-x11.cpp
     58        autoresize.cpp
    5859 VBoxClient_LIBS += \
    5960        Xext Xmu
  • trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp

    r17004 r18360  
    4242#include <vector>
    4343
     44#include "VBoxClient.h"
    4445#include "clipboard.h"
    4546
     
    13621363}
    13631364
    1364 
    13651365/**
    13661366 * Connect the guest clipboard to the host.
     
    13781378    /* Initialise the termination semaphore. */
    13791379    RTSemEventCreate(&g_ctx.terminating);
     1380
     1381    /* Initialise threading in X11 and in Xt. */
     1382    if (!XInitThreads() || !XtToolkitThreadInitialize())
     1383    {
     1384        LogRel(("VBoxClient: error initialising threads in X11, exiting.\n"));
     1385        return VERR_NOT_SUPPORTED;
     1386    }
    13801387
    13811388    rc = VbglR3ClipboardConnect(&g_ctx.client);
     
    14871494}
    14881495
     1496class ClipboardService : public VBoxClient::Service
     1497{
     1498public:
     1499    virtual const char *getPidFilePath()
     1500    {
     1501        return ".vboxclient-clipboard.pid";
     1502    }
     1503    virtual int run()
     1504    {
     1505        int rc = vboxClipboardConnect();
     1506        if (RT_SUCCESS(rc))
     1507            rc = vboxClipboardMain();
     1508        return rc;
     1509    }
     1510    virtual void cleanup()
     1511    {
     1512        /* Nothing to do. */
     1513    }
     1514};
     1515
     1516VBoxClient::Service *VBoxClient::GetClipboardService()
     1517{
     1518    return new ClipboardService;
     1519}
  • trunk/src/VBox/Additions/x11/VBoxClient/main.cpp

    r18320 r18360  
    2121 */
    2222
    23 #include <VBox/VBoxGuest.h>
    24 #include <VBox/log.h>
     23#include <sys/types.h>
     24#include <stdlib.h>       /* For exit */
     25#include <stdio.h>
     26#include <string.h>
     27#include <unistd.h>
     28#include <errno.h>
     29#include <signal.h>
     30
     31#include <iprt/env.h>
    2532#include <iprt/initterm.h>
    2633#include <iprt/path.h>
    2734#include <iprt/stream.h>
    28 
    29 #include <sys/types.h>
    30 #include <stdlib.h>       /* For exit */
    31 #include <stdio.h>
    32 #include <unistd.h>
    33 #include <errno.h>
    34 #include <signal.h>
    35 
    36 #include <X11/Xlib.h>
    37 #include <X11/Intrinsic.h>
    38 
    39 #include "clipboard.h"
     35#include <iprt/string.h>
     36#include <VBox/VBoxGuest.h>
     37#include <VBox/log.h>
     38
     39#include "VBoxClient.h"
    4040
    4141#ifdef DYNAMIC_RESIZE
     
    5050static int (*gpfnOldIOErrorHandler)(Display *) = NULL;
    5151
    52 /* Make these global so that the destructors are called if we make an "emergency exit",
    53    i.e. a (handled) signal or an X11 error. */
    54 #ifdef DYNAMIC_RESIZE
    55 VBoxGuestDisplayChangeMonitor gDisplayChange;
    56 # ifdef SEAMLESS_GUEST
    57     /** Our instance of the seamless class.  This only makes sense if dynamic resizing
    58         is enabled. */
    59     VBoxGuestSeamless gSeamless;
    60 # endif /* SEAMLESS_GUEST defined */
    61 #endif /* DYNAMIC_RESIZE */
    62 #ifdef VBOX_X11_CLIPBOARD
    63     VBoxGuestClipboard gClipboard;
    64 #endif
    65 
    66 /**
    67  * Drop the programmes privileges to the caller's.
    68  * @returns IPRT status code
    69  * @todo move this into the R3 guest library
    70  */
    71 int vboxClientDropPrivileges(void)
    72 {
    73     int rc = VINF_SUCCESS;
    74     int rcSystem, rcErrno;
    75 
    76     LogFlowFunc(("\n"));
    77 #ifdef _POSIX_SAVED_IDS
    78     rcSystem = setuid(getuid());
    79 #else
    80     rcSystem = setreuid(-1, getuid());
    81 #endif
    82     if (rcSystem < 0)
    83     {
    84         rcErrno = errno;
    85         rc = RTErrConvertFromErrno(rcErrno);
    86         LogRel(("VBoxClient: failed to drop privileges, error %Rrc.\n", rc));
    87     }
    88     LogFlowFunc(("returning %Rrc\n", rc));
    89     return rc;
     52/** Object representing the service we are running.  This has to be global
     53 * so that the cleanup routine can access it. */
     54VBoxClient::Service *g_pService;
     55/** The name of our pidfile.  It is global for the benefit of the cleanup
     56 * routine. */
     57static char *g_pszPidFile;
     58/** The file handle of our pidfile.  It is global for the benefit of the
     59 * cleanup routine. */
     60static RTFILE g_hPidFile;
     61
     62/** Clean up if we get a signal or something.  This is extern so that we
     63 * can call it from other compilation units. */
     64void VBoxClient::CleanUp()
     65{
     66    if (g_pService)
     67    {
     68        g_pService->cleanup();
     69        delete g_pService;
     70    }
     71    if (g_pszPidFile && g_hPidFile)
     72        VbglR3ClosePidFile(g_pszPidFile, g_hPidFile);
     73    VbglR3Term();
     74    exit(0);
     75}
     76
     77/**
     78 * A standard signal handler which cleans up and exits.
     79 */
     80void vboxClientSignalHandler(int cSignal)
     81{
     82    Log(("VBoxClient: terminated with signal %d\n", cSignal));
     83    /** Disable seamless mode */
     84    RTPrintf(("VBoxClient: terminating...\n"));
     85    VBoxClient::CleanUp();
    9086}
    9187
     
    112108    XGetErrorText(pDisplay, pError->error_code, errorText, sizeof(errorText));
    113109    LogRel(("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));
    114     /** Disable seamless mode */
    115     VbglR3SeamlessSetCap(false);
    116     VbglR3Term();
    117     exit(1);
     110    VBoxClient::CleanUp();
     111    return 0;  /* We should never reach this. */
    118112}
    119113
     
    122116 * when X exits.
    123117 */
    124 int vboxClientXLibIOErrorHandler(Display *pDisplay)
     118static int vboxClientXLibIOErrorHandler(Display *pDisplay)
    125119{
    126120    Log(("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"));
    127     /** Disable seamless mode */
    128     VbglR3SeamlessSetCap(false);
    129     VbglR3Term();
    130     return gpfnOldIOErrorHandler(pDisplay);
    131 }
    132 
    133 /**
    134  * A standard signal handler which cleans up and exits.  Our global static objects will
    135  * be cleaned up properly as we exit using "exit".
    136  */
    137 void vboxClientSignalHandler(int cSignal)
    138 {
    139     Log(("VBoxClient: terminated with signal %d\n", cSignal));
    140     /** Disable seamless mode */
    141     VbglR3SeamlessSetCap(false);
    142     RTPrintf(("VBoxClient: terminating...\n"));
    143     /* don't call VbglR3Term() here otherwise the /dev/vboxadd filehandle is closed */
    144     /* Our pause() call will now return and exit. */
    145 }
    146 
    147 /**
    148  * Reset all standard termination signals to call our signal handler, which cleans up
    149  * and exits.
     121    VBoxClient::CleanUp();
     122    return 0;  /* We should never reach this. */
     123}
     124
     125/**
     126 * Reset all standard termination signals to call our signal handler, which
     127 * cleans up and exits.
    150128 */
    151129void vboxClientSetSignalHandlers(void)
     
    174152void vboxClientUsage(const char *pcszFileName)
    175153{
    176     RTPrintf("Usage: %s [-d|--nodaemon]\n", pcszFileName);
     154    RTPrintf("Usage: %s --clipboard|--autoresize|--seamless [-d|--nodaemon]\n", pcszFileName);
    177155    RTPrintf("Start the VirtualBox X Window System guest services.\n\n");
    178156    RTPrintf("Options:\n");
    179     RTPrintf("  -d, --nodaemon   do not lower privileges and continue running as a system\n");
    180     RTPrintf("                   service\n");
     157    RTPrintf("  --clipboard      start the shared clipboard service\n");
     158    RTPrintf("  --autoresize     start the display auto-resize service\n");
     159    RTPrintf("  --seamless       start the seamless windows service\n");
     160    RTPrintf("  -d, --nodaemon   continue running as a system service\n");
    181161    RTPrintf("\n");
    182162    exit(0);
     
    191171    const char *pszFileName = RTPathFilename(argv[0]);
    192172    bool fDaemonise = true;
     173    /* Have any fatal errors occurred yet? */
     174    bool fSuccess = true;
     175    /* Do we know which service we wish to run? */
     176    bool fHaveService = false;
    193177
    194178    if (NULL == pszFileName)
     
    204188        if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--nodaemon"))
    205189            fDaemonise = false;
     190        else if (!strcmp(argv[i], "--clipboard"))
     191        {
     192            if (g_pService == NULL)
     193                g_pService = VBoxClient::GetClipboardService();
     194            else
     195                fSuccess = false;
     196        }
     197        else if (!strcmp(argv[i], "--autoresize"))
     198        {
     199            if (g_pService == NULL)
     200                g_pService = VBoxClient::GetAutoResizeService();
     201            else
     202                fSuccess = false;
     203        }
     204        else if (!strcmp(argv[i], "--seamless"))
     205        {
     206            if (g_pService == NULL)
     207                g_pService = VBoxClient::GetSeamlessService();
     208            else
     209                fSuccess = false;
     210        }
    206211        else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
    207212        {
     
    216221        }
    217222    }
     223    if (!fSuccess || !g_pService)
     224    {
     225        vboxClientUsage(pszFileName);
     226        exit(1);
     227    }
    218228    if (fDaemonise)
    219229    {
     
    221231        if (RT_FAILURE(rc))
    222232        {
    223             RTPrintf("VBoxClient: failed to daemonize. exiting.\n");
     233            RTPrintf("VBoxClient: failed to daemonize.  Exiting.\n");
     234            Log(("VBoxClient: failed to daemonize.  Exiting.\n"));
    224235#ifdef DEBUG
    225236            RTPrintf("Error %Rrc\n", rc);
     
    228239        }
    229240    }
     241    const char *pszHome = RTEnvGet("HOME");
     242    if (pszHome == NULL)
     243    {
     244        RTPrintf("VBoxClient: failed to get home directory.  Exiting.\n");
     245        Log(("VBoxClient: failed to get home directory.  Exiting.\n"));
     246        return 1;
     247    }
     248    if (RTStrAPrintf(&g_pszPidFile, "%s/%s", pszHome, g_pService->getPidFilePath()) == -1)
     249    if (pszHome == NULL)
     250    {
     251        RTPrintf("VBoxClient: out of memory.  Exiting.\n");
     252        Log(("VBoxClient: out of memory.  Exiting.\n"));
     253        return 1;
     254    }
    230255    /* Initialise the guest library. */
    231     if (RT_FAILURE(VbglR3Init()))
     256    if (RT_FAILURE(VbglR3InitUser()))
    232257    {
    233258        RTPrintf("Failed to connect to the VirtualBox kernel service\n");
    234         return 1;
    235     }
    236     if (fDaemonise && RT_FAILURE(vboxClientDropPrivileges()))
    237         return 1;
    238     LogRel(("VBoxClient: starting...\n"));
    239     /* Initialise threading in X11 and in Xt. */
    240     if (!XInitThreads() || !XtToolkitThreadInitialize())
    241     {
    242         LogRel(("VBoxClient: error initialising threads in X11, exiting.\n"));
    243         return 1;
    244     }
     259        Log(("Failed to connect to the VirtualBox kernel service\n"));
     260        return 1;
     261    }
     262    if (g_pszPidFile && RT_FAILURE(VbglR3PidFile(g_pszPidFile, &g_hPidFile)))
     263    {
     264        RTPrintf("Failed to create a pidfile.  Exiting.\n");
     265        Log(("Failed to create a pidfile.  Exiting.\n"));
     266        VbglR3Term();
     267        return 1;
     268    }
     269    /* Set signal handlers to clean up on exit. */
     270    vboxClientSetSignalHandlers();
    245271    /* Set an X11 error handler, so that we don't die when we get unavoidable errors. */
    246272    XSetErrorHandler(vboxClientXLibErrorHandler);
    247273    /* Set an X11 I/O error handler, so that we can shutdown properly on fatal errors. */
    248     gpfnOldIOErrorHandler = XSetIOErrorHandler(vboxClientXLibIOErrorHandler);
    249     vboxClientSetSignalHandlers();
    250     try
    251     {
    252 #ifdef VBOX_X11_CLIPBOARD
    253         /* Connect to the host clipboard. */
    254         LogRel(("VBoxClient: starting clipboard Guest Additions...\n"));
    255         rcClipboard = gClipboard.init();
    256         if (RT_FAILURE(rcClipboard))
    257         {
    258             LogRel(("VBoxClient: vboxClipboardConnect failed with rc = %Rrc\n", rcClipboard));
    259         }
    260 #endif  /* VBOX_X11_CLIPBOARD defined */
    261 #ifdef DYNAMIC_RESIZE
    262         LogRel(("VBoxClient: starting dynamic guest resizing...\n"));
    263         rc = gDisplayChange.init();
    264         if (RT_FAILURE(rc))
    265         {
    266             LogRel(("VBoxClient: failed to start dynamic guest resizing, rc = %Rrc\n", rc));
    267         }
    268 # ifdef SEAMLESS_GUEST
    269         if (RT_SUCCESS(rc))
    270         {
    271             LogRel(("VBoxClient: starting seamless Guest Additions...\n"));
    272             rc = gSeamless.init();
    273             if (RT_FAILURE(rc))
    274             {
    275                 LogRel(("VBoxClient: failed to start seamless Additions, rc = %Rrc\n", rc));
    276             }
    277         }
    278 # endif /* SEAMLESS_GUEST defined */
    279 #endif /* DYNAMIC_RESIZE defined */
    280     }
    281     catch (std::exception e)
    282     {
    283         LogRel(("VBoxClient: failed to initialise Guest Additions - caught exception: %s\n", e.what()));
    284         rc = VERR_UNRESOLVED_ERROR;
    285     }
    286     catch (...)
    287     {
    288         LogRel(("VBoxClient: failed to initialise Guest Additions - caught unknown exception.\n"));
    289         rc = VERR_UNRESOLVED_ERROR;
    290     }
    291     LogRel(("VBoxClient: sleeping...\n"));
    292     pause();
    293     LogRel(("VBoxClient: exiting...\n"));
    294     try
    295     {
    296         /* r=frank: Why all these 2s delays? What are we waiting for? */
    297 #ifdef DYNAMIC_RESIZE
    298 # ifdef SEAMLESS_GUEST
    299         LogRel(("VBoxClient: shutting down seamless Guest Additions...\n"));
    300         gSeamless.uninit(2000);
    301 # endif /* SEAMLESS_GUEST defined */
    302         LogRel(("VBoxClient: shutting down dynamic guest resizing...\n"));
    303         gDisplayChange.uninit(2000);
    304 #endif /* DYNAMIC_RESIZE defined */
    305 #ifdef VBOX_X11_CLIPBOARD
    306         /* Connect to the host clipboard. */
    307         LogRel(("VBoxClient: shutting down clipboard Guest Additions...\n"));
    308         gClipboard.uninit(2000);
    309 #endif  /* VBOX_X11_CLIPBOARD defined */
    310     }
    311     catch (std::exception e)
    312     {
    313         LogRel(("VBoxClient: failed to shut down Guest Additions - caught exception: %s\n", e.what()));
    314         rc = VERR_UNRESOLVED_ERROR;
    315     }
    316     catch (...)
    317     {
    318         LogRel(("VBoxClient: failed to shut down Guest Additions - caught unknown exception.\n"));
    319         rc = VERR_UNRESOLVED_ERROR;
    320     }
    321     VbglR3Term();
    322     return RT_SUCCESS(rc) ? 0 : 1;
    323 }
     274    XSetIOErrorHandler(vboxClientXLibIOErrorHandler);
     275    g_pService->run();
     276    VBoxClient::CleanUp();
     277    return 1;  /* We should never get here. */
     278}
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette