VirtualBox

Changeset 50346 in vbox


Ignore:
Timestamp:
Feb 6, 2014 2:40:20 PM (11 years ago)
Author:
vboxsync
Message:

Additions/x11/VBoxClient: more clean-up.

Location:
trunk/src/VBox/Additions/x11/VBoxClient
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp

    r50338 r50346  
    9696 *
    9797 * @note This class does not contain its own event thread, so an external thread must
    98  *       call nextEvent() for as long as events are wished.
     98 *       call nextConfigurationEvent() for as long as events are wished.
    9999 * @todo This function should switch the guest to fullscreen mode.
    100100 */
     
    289289 * @note Called from the guest event thread.
    290290 */
    291 void SeamlessX11::nextEvent(void)
     291void SeamlessX11::nextConfigurationEvent(void)
    292292{
    293293    XEvent event;
     
    299299    {
    300300        updateRects();
    301         mHost->notify(mpRects, mcRects);
     301        mHost->sendRegionUpdate(mpRects, mcRects);
    302302    }
    303303    mChanged = false;
     
    528528 * @note This function should only be called from the host event thread.
    529529 */
    530 bool SeamlessX11::interruptEvent(void)
     530bool SeamlessX11::interruptEventWait(void)
    531531{
    532532    bool rc = false;
  • trunk/src/VBox/Additions/x11/VBoxClient/seamless-x11.h

    r50338 r50346  
    4141{
    4242public:
    43     virtual void notify(RTRECT *pRects, size_t cRects) = 0;
     43    virtual void sendRegionUpdate(RTRECT *pRects, size_t cRects) = 0;
    4444};
    4545
     
    216216    void uninit(void)
    217217    {
    218         if (0 != mHost)
    219         {
     218        if (mHost)
    220219            stop();
    221         }
    222         mHost = 0;
     220        mHost = NULL;
     221        if (mDisplay)
     222            XCloseDisplay(mDisplay);
     223        mDisplay = NULL;
    223224    }
    224225
     
    237238
    238239    /** Process next event in the guest event queue - called by the event thread. */
    239     void nextEvent(void);
     240    void nextConfigurationEvent(void);
    240241    /** Wake up the event thread if it is waiting for an event so that it can exit. */
    241     bool interruptEvent(void);
     242    bool interruptEventWait(void);
    242243
    243244    /* Methods to handle X11 events.  These are public so that the unit test
     
    255256    {
    256257        uninit();
    257         if (mDisplay)
    258             XCloseDisplay(mDisplay);
    259258    }
    260259};
  • trunk/src/VBox/Additions/x11/VBoxClient/seamless.cpp

    r50338 r50346  
    3131#include "seamless.h"
    3232
    33 /**
    34  * Start the service.
    35  * @returns iprt status value
     33SeamlessMain::SeamlessMain(void)
     34{
     35    LogRelFlowFunc(("\n"));
     36    mX11MonitorThread = NIL_RTTHREAD;
     37    mX11MonitorThreadStopping = false;
     38    mHostEventThread = NIL_RTTHREAD;
     39    mHostEventThreadRunning = false;
     40    mHostEventThreadStopping = false;
     41}
     42
     43SeamlessMain::~SeamlessMain()
     44{
     45    LogRelFlowFunc(("\n"));
     46    stop();
     47}
     48
     49/**
     50 * Start the main service thread which listens for host state change
     51 * notifications.
     52 * @returns iprt status value.  Service will be set to the stopped state on
     53 *          failure.
    3654 */
    3755int SeamlessMain::start(void)
    3856{
    39     int rc = VERR_NOT_SUPPORTED;
    40 
    41     LogRelFlowFunc(("\n"));
    42     if (mThread)  /* Assertion */
    43     {
    44         LogRel(("VBoxClient: seamless service started twice!\n"));
    45         return VERR_INTERNAL_ERROR;
    46     }
    47     rc = VbglR3CtlFilterMask(VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST, 0);
    48     if (RT_FAILURE(rc))
    49     {
    50         LogRel(("VBoxClient (seamless): failed to set the guest IRQ filter mask, rc=%Rrc\n", rc));
    51     }
    52     rc = VbglR3SeamlessSetCap(true);
    53     if (RT_SUCCESS(rc))
    54     {
    55         LogRel(("VBoxClient: enabled seamless capability on host.\n"));
     57    int rc;
     58    const char *pszStage;
     59
     60    LogRelFlowFunc(("\n"));
     61    do {
     62        pszStage = "Checking that we are not already running";
     63        rc = VERR_INTERNAL_ERROR;
     64        if (mHostEventThread)  /* Assertion */
     65            break;
     66        pszStage = "Connecting to the X server";
     67        rc = mX11Monitor.init(this);
     68        if (RT_FAILURE(rc))
     69            break;
    5670        /* Create a thread to wait for requests from the host.  This is currently
    5771         * done on a separate thread as the main thread monitors the X11 server
     
    5973        /** @todo Move the disconnection monitoring to its own thread (better, the
    6074         *  VT monitor thread) and run this logic on the main service thread. */
    61         rc = RTThreadCreate(&mThread, threadFunction, this, 0,
    62                             RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
    63                             "Host events");
    64         if (RT_FAILURE(rc))
    65         {
    66             LogRel(("VBoxClient: failed to start seamless event thread, rc=%Rrc.  Disabled seamless capability on host again.\n", rc));
    67             VbglR3SeamlessSetCap(false);
    68         }
    69     }
     75        pszStage = "Starting host event thread";
     76        rc = startHostEventThread();
     77        if (RT_FAILURE(rc))
     78            break;
     79        pszStage = "Setting guest IRQ filter mask";
     80        rc = VbglR3CtlFilterMask(VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST, 0);
     81        if (RT_FAILURE(rc))
     82            break;
     83        pszStage = "Reporting support for seamless capability";
     84        rc = VbglR3SeamlessSetCap(true);
     85        if (RT_FAILURE(rc))
     86            break;
     87    } while(0);
    7088    if (RT_FAILURE(rc))
    7189    {
    72         LogRel(("VBoxClient (seamless): failed to enable seamless capability on host, rc=%Rrc\n", rc));
     90        LogRel(("VBoxClient (seamless): failed to start.  Stage: \"%s\"  Error: %Rrc\n",
     91                pszStage, rc));
     92        stop();
    7393    }
    7494    LogRelFlowFunc(("returning %Rrc\n", rc));
     
    80100{
    81101    LogRelFlowFunc(("\n"));
    82     if (!mThread)  /* Assertion */
    83         LogRel(("VBoxClient: tried to stop seamless service which is not running!\n"));
    84     else
    85         stopThread();
    86     if (mX11MonitorRTThread)
    87         stopX11Thread();
     102    VbglR3SeamlessSetCap(false);
    88103    VbglR3CtlFilterMask(0, VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST);
    89     VbglR3SeamlessSetCap(false);
     104    if (mHostEventThread)
     105        stopHostEventThread();
     106    stopX11MonitorThread();
     107    mX11Monitor.uninit();
    90108    LogRelFlowFunc(("returning\n"));
    91109}
     
    96114 * @returns        IRPT return code.
    97115 */
    98 int SeamlessMain::nextEvent(void)
     116int SeamlessMain::nextStateChangeEvent(void)
    99117{
    100118    VMMDevSeamlessMode newMode = VMMDev_Seamless_Disabled;
     
    109127            /* A simplified seamless mode, obtained by making the host VM window borderless and
    110128              making the guest desktop transparent. */
    111 #ifdef DEBUG
    112                 LogRelFunc(("VMMDev_Seamless_Visible_Region request received (VBoxClient).\n"));
    113 #endif
    114                 mX11ThreadStopping = false;
     129                LogRelFlowFunc(("VMMDev_Seamless_Visible_Region request received (VBoxClient).\n"));
    115130                /** @todo Do something on failure, like bail out. */
    116                 if (RT_FAILURE(RTThreadCreate(&mX11MonitorRTThread,
    117                                x11ThreadFunction, this, 0, RTTHREADTYPE_MSG_PUMP,
    118                                RTTHREADFLAGS_WAITABLE, "X11 events")))
    119                     LogRelFunc(("Warning: failed to start X11 monitor thread (VBoxClient).\n"));
     131                startX11MonitorThread();
    120132                break;
    121133            case VMMDev_Seamless_Host_Window:
     
    127139                /* fall through to case VMMDev_Seamless_Disabled */
    128140            case VMMDev_Seamless_Disabled:
    129 #ifdef DEBUG
    130                 LogRelFunc(("VMMDev_Seamless_Disabled set (VBoxClient).\n"));
    131 #endif
    132                 if (mX11MonitorRTThread)
    133                     stopX11Thread();
    134                 else
    135                     LogRelThisFunc(("Attempted to stop X11 monitor thread which is not running (VBoxClient)!\n"));
     141                LogRelFlowFunc(("VMMDev_Seamless_Disabled set (VBoxClient).\n"));
     142                stopX11MonitorThread();
    136143        }
    137144    }
     
    147154 * Update the set of visible rectangles in the host.
    148155 */
    149 void SeamlessMain::notify(RTRECT *pRects, size_t cRects)
     156void SeamlessMain::sendRegionUpdate(RTRECT *pRects, size_t cRects)
    150157{
    151158    LogRelFlowFunc(("\n"));
     
    161168
    162169/**
    163  * The actual event thread function.
    164  */
    165 int SeamlessMain::threadFunction(RTTHREAD self, void *pvUser)
     170 * Thread to listen for seamless state change notifications from the host.
     171 */
     172int SeamlessMain::hostEventThread(RTTHREAD self, void *pvUser)
    166173{
    167174    SeamlessMain *pHost = (SeamlessMain *)pvUser;
    168175
    169176    LogRelFlowFunc(("\n"));
    170     pHost->mThreadRunning = true;
     177    pHost->mHostEventThreadRunning = true;
    171178    if (0 != pHost)
    172179    {
    173         while (!pHost->mThreadStopping)
     180        while (!pHost->mHostEventThreadStopping)
    174181        {
    175             if (RT_FAILURE(pHost->nextEvent()) && !pHost->mThreadStopping)
     182            /* This thread is stopped by setting @a mHostEventThreadStopping
     183             * and sending a cancel to the state change event wait, see below.
     184             */
     185            if (   RT_FAILURE(pHost->nextStateChangeEvent())
     186                && !pHost->mHostEventThreadStopping)
    176187            {
    177188                /* If we are not stopping, sleep for a bit to avoid using up too
     
    181192        }
    182193    }
    183     pHost->mThreadRunning = false;
    184     LogRelFlowFunc(("returning VINF_SUCCESS\n"));
     194    pHost->mHostEventThreadRunning = false;
    185195    return VINF_SUCCESS;
    186196}
    187197
    188198/**
    189  * Send a signal to the thread that it should exit
    190  */
    191 void SeamlessMain::stopThread()
     199 * Start the seamless state change notification listener thread.
     200 */
     201int SeamlessMain::startHostEventThread()
     202{
     203    int rc;
     204
     205    mHostEventThreadStopping = false;
     206    rc = RTThreadCreate(&mHostEventThread, hostEventThread, this, 0,
     207                        RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
     208                        "Host events");
     209    if (RT_FAILURE(rc))
     210        LogRel(("VBoxClient: failed to start seamless event thread, rc=%Rrc.\n",
     211                rc));
     212    return rc;
     213}
     214
     215/**
     216 * Send a signal to the host event thread that it should exit and poke it.
     217 */
     218void SeamlessMain::stopHostEventThread()
    192219{
    193220    int rc;
     
    200227     *       yield() should give it time to get to one of places mentioned above.
    201228     */
    202     mThreadStopping = true;
    203     for (int i = 0; (i < 5) && mThreadRunning; ++i)
     229    mHostEventThreadStopping = true;
     230    for (int i = 0; (i < 5) && mHostEventThreadRunning; ++i)
    204231    {
    205232        cancelEvent();
    206233        RTThreadYield();
    207234    }
    208     rc = RTThreadWait(mThread, RT_INDEFINITE_WAIT, NULL);
     235    rc = RTThreadWait(mHostEventThread, RT_INDEFINITE_WAIT, NULL);
    209236    if (RT_SUCCESS(rc))
    210         mThread = NIL_RTTHREAD;
     237        mHostEventThread = NIL_RTTHREAD;
    211238    else
    212239        LogRelThisFunc(("Failed to stop seamless event thread, rc=%Rrc!\n",
     
    216243
    217244/**
    218  * The actual X11 event thread function.
    219  */
    220 int SeamlessMain::x11ThreadFunction(RTTHREAD self, void *pvUser)
     245 * The actual X11 window configuration change monitor thread function.
     246 */
     247int SeamlessMain::x11MonitorThread(RTTHREAD self, void *pvUser)
    221248{
    222249    SeamlessMain *pHost = (SeamlessMain *)pvUser;
     
    227254    if (RT_SUCCESS(rc))
    228255    {
    229         while (!pHost->mX11ThreadStopping)
    230         {
    231             pHost->mX11Monitor.nextEvent();
    232         }
     256        while (!pHost->mX11MonitorThreadStopping)
     257            pHost->mX11Monitor.nextConfigurationEvent();
    233258        pHost->mX11Monitor.stop();
    234259    }
     
    238263
    239264/**
     265 * Start the X11 window configuration change monitor thread.
     266 */
     267int SeamlessMain::startX11MonitorThread(void)
     268{
     269    int rc;
     270
     271    mX11MonitorThreadStopping = false;
     272    rc = RTThreadCreate(&mX11MonitorThread, x11MonitorThread, this, 0,
     273                        RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
     274                        "X11 events");
     275    if (RT_FAILURE(rc))
     276        LogRelFunc(("Warning: failed to start X11 monitor thread (VBoxClient).\n"));
     277    return rc;
     278}
     279
     280/**
    240281 * Send a signal to the thread function that it should exit
    241282 */
    242 void SeamlessMain::stopX11Thread(void)
    243 {
    244     int rc;
    245 
    246     mX11ThreadStopping = true;
    247     mX11Monitor.interruptEvent();
    248     rc = RTThreadWait(mX11MonitorRTThread, RT_INDEFINITE_WAIT, NULL);
     283void SeamlessMain::stopX11MonitorThread(void)
     284{
     285    int rc;
     286
     287    mX11MonitorThreadStopping = true;
     288    if (!mX11MonitorThread)
     289        return;
     290    mX11Monitor.interruptEventWait();
     291    rc = RTThreadWait(mX11MonitorThread, RT_INDEFINITE_WAIT, NULL);
    249292    if (RT_SUCCESS(rc))
    250         mX11MonitorRTThread = NIL_RTTHREAD;
     293        mX11MonitorThread = NIL_RTTHREAD;
    251294    else
    252295        LogRelThisFunc(("Failed to stop X11 monitor thread, rc=%Rrc!\n",
     
    269312    virtual int run(bool fDaemonised /* = false */)
    270313    {
     314        Display *pDisplay = NULL;
     315        const char *pszStage;
     316        XEvent ev;
    271317        int rc;
    272318
    273         if (mIsInitialised)  /* Assertion */
     319        do {
     320            pszStage = "Checking that we are not already running";
     321            rc = VERR_INTERNAL_ERROR;
     322            if (mIsInitialised)  /* Assertion */
     323                break;
     324            pszStage = "Connecting to the X server";
     325            rc = VERR_INTERNAL_ERROR;
     326            pDisplay = XOpenDisplay(NULL);
     327            if (!pDisplay)
     328                break;
     329            pszStage = "Starting the service";
     330            rc = mSeamless.start();
     331            if (RT_FAILURE(rc))
     332                break;
     333        } while(0);
     334        if (RT_FAILURE(rc))
    274335        {
    275             LogRelFunc(("error: called a second time! (VBoxClient)\n"));
    276             rc = VERR_INTERNAL_ERROR;
    277         }
    278         if (RT_SUCCESS(rc))
    279             rc = mSeamless.init();
    280         if (RT_SUCCESS(rc))
    281             rc = mSeamless.start();
    282         if (RT_SUCCESS(rc))
    283             mIsInitialised = true;
    284         if (RT_FAILURE(rc))
    285         {
    286             LogRelFunc(("returning %Rrc (VBoxClient)\n", rc));
     336            LogRelFunc(("VBoxClient seamless service control: failed at stage: \"%s\".  Error: %Rrc\n",
     337                        pszStage, rc));
     338            mSeamless.stop();
     339            if (pDisplay)
     340                XCloseDisplay(pDisplay);
    287341            return rc;
    288342        }
     343        mIsInitialised = true;
    289344        /* Stay running as long as X does... */
    290         Display *pDisplay = XOpenDisplay(NULL);
    291         XEvent ev;
    292345        while (true)
    293346            XNextEvent(pDisplay, &ev);
  • trunk/src/VBox/Additions/x11/VBoxClient/seamless.h

    r50338 r50346  
    3131class SeamlessMain : public SeamlessHostProxy
    3232{
    33 public:
    34     /** Events which can be reported by this class */
    35     enum meEvent
    36     {
    37         /** Empty event */
    38         NONE,
    39         /** Request to enable seamless mode */
    40         ENABLE,
    41         /** Request to disable seamless mode */
    42         DISABLE
    43     };
    44 
    4533private:
    4634    // We don't want a copy constructor or assignment operator
     
    4836    SeamlessMain& operator=(const SeamlessMain&);
    4937
    50     /** Have we been initialised yet? */
    51     bool mIsInitialised;
    5238    /** X11 event monitor object */
    5339    SeamlessX11 mX11Monitor;
     
    5541    /** Thread to start and stop when we enter and leave seamless mode which
    5642     *  monitors X11 windows in the guest. */
    57     RTTHREAD mX11MonitorRTThread;
     43    RTTHREAD mX11MonitorThread;
    5844    /** Should the X11 monitor thread be stopping? */
    59     volatile bool mX11ThreadStopping;
     45    volatile bool mX11MonitorThreadStopping;
    6046    /** Host seamless event thread. */
    61     RTTHREAD mThread;
     47    RTTHREAD mHostEventThread;
    6248    /** Is the thread running? */
    63     volatile bool mThreadRunning;
     49    volatile bool mHostEventThreadRunning;
    6450    /** Should the thread be stopping? */
    65     volatile bool mThreadStopping;
     51    volatile bool mHostEventThreadStopping;
    6652
    6753    /**
     
    7157     * @returns        IRPT return code.
    7258     */
    73     int nextEvent(void);
     59    int nextStateChangeEvent(void);
    7460
    7561    /**
    76      * Interrupt an event wait and cause nextEvent() to return immediately.
     62     * Interrupt an event wait and cause nextStateChangeEvent() to return immediately.
    7763     */
    7864    void cancelEvent(void) { VbglR3InterruptEventWaits(); }
     
    8066    /** Thread function to query seamless activation and deactivation events
    8167     *  from the host. */
    82     static DECLCALLBACK(int) threadFunction(RTTHREAD self, void *pvUser);
     68    static DECLCALLBACK(int) hostEventThread(RTTHREAD self, void *pvUser);
     69
     70    /** Helper to start the seamless state change notification listener
     71     * thread. */
     72    int startHostEventThread();
    8373
    8474    /** Helper to stop the event query thread again. */
    85     void stopThread();
     75    void stopHostEventThread();
    8676
    8777    /** Thread function to monitor X11 window configuration changes. */
    88     static DECLCALLBACK(int) x11ThreadFunction(RTTHREAD self, void *pvUser);
     78    static DECLCALLBACK(int) x11MonitorThread(RTTHREAD self, void *pvUser);
     79
     80    /** Helper to start the X11 monitor thread. */
     81    int startX11MonitorThread(void);
    8982
    9083    /** Helper to stop the X11 monitor thread again. */
    91     void stopX11Thread(void);
     84    void stopX11MonitorThread(void);
    9285
    9386public:
    94     /**
    95      * Initialise the guest and ensure that it is capable of handling seamless mode
    96      * @param   pX11Monitor Object to monitor X11 guest windows.
    97      *
    98      * @returns iprt status code
    99      */
    100     int init(void)
    101     {
    102         int rc;
    103 
    104         LogRelFlowFunc(("\n"));
    105         if (mIsInitialised)
    106             return VERR_INTERNAL_ERROR;
    107         rc = mX11Monitor.init(this);
    108         if (RT_SUCCESS(rc))
    109             mIsInitialised = true;
    110         return rc;
    111     }
     87    SeamlessMain(void);
     88    ~SeamlessMain();
    11289
    11390    /**
     
    11996    /**
    12097     * Stops the service.
    121      * @param cMillies how long to wait for the thread to exit
    12298     */
    12399    void stop();
     
    126102     * Update the set of visible rectangles in the host.
    127103     */
    128     virtual void notify(RTRECT *pRects, size_t cRects);
    129 
    130     SeamlessMain(void)
    131     {
    132         mIsInitialised = false;
    133         mX11MonitorRTThread = NIL_RTTHREAD;
    134         mX11ThreadStopping = false;
    135         mThread = NIL_RTTHREAD;
    136         mThreadRunning = false;
    137         mThreadStopping = false;
    138     }
    139 
    140     ~SeamlessMain()
    141     {
    142         LogRelFlowFunc(("\n"));
    143         if (mThread)
    144             stop();
    145         LogRelFlowFunc(("returning\n"));
    146     }
     104    virtual void sendRegionUpdate(RTRECT *pRects, size_t cRects);
    147105};
    148106
  • trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11-auto.cpp

    r50338 r50346  
    303303public:
    304304    testHost() : mfNotified(false) {}
    305     virtual void notify(RTRECT *pRects, size_t cRects)
     305    virtual void sendRegionUpdate(RTRECT *pRects, size_t cRects)
    306306    {
    307307        mfNotified = true;
     
    625625        ++cErrs;
    626626    }
    627     subject.nextEvent();
     627    subject.nextConfigurationEvent();
    628628    if (!host.isNotified())
    629629    {
     
    633633    }
    634634    smlsSetNextEvent(0, 0);
    635     subject.nextEvent();
     635    subject.nextConfigurationEvent();
    636636    if (!host.isNotified())
    637637    {
  • trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp

    r50338 r50346  
    3535                 pRects[i].yBottom);
    3636    }
    37     return true;
     37    return VINF_SUCCESS;
    3838}
    3939
     
    4242    RTPrintf("%s\n", bState ? "Seamless capability set"
    4343                            : "Seamless capability unset");
    44     return true;
     44    return VINF_SUCCESS;
    4545}
    4646
     
    4949    RTPrintf("IRQ filter mask changed.  Or mask: 0x%x.  Not mask: 0x%x\n",
    5050             u32OrMask, u32NotMask);
    51     return true;
     51    return VINF_SUCCESS;
    5252}
    5353
     
    7070        }
    7171    }
    72     return true;
     72    return rc;
    7373}
    7474
     
    121121    SeamlessMain seamless;
    122122    LogRel(("Starting seamless Guest Additions...\n"));
    123     rc = seamless.init();
     123    rc = seamless.start();
    124124    if (rc != VINF_SUCCESS)
    125125    {
    126         RTPrintf("Failed to initialise seamless Additions, rc = %d\n", rc);
     126        RTPrintf("Failed to initialise seamless Additions, rc = %Rrc\n", rc);
    127127    }
    128128    RTStrmGetLine(g_pStdIn, ach, sizeof(ach));
Note: See TracChangeset for help on using the changeset viewer.

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