VirtualBox

Ignore:
Timestamp:
Nov 16, 2009 3:50:47 PM (15 years ago)
Author:
vboxsync
Message:

Main,GuestProperties: Moved the HGCM shutdown down after we've powered off the VM. Ditto for moving the guest properties to VBoxSVC. Explicitly flush the guest property change notifications before moving them. Added a handleUnexpectedExceptions to Console that is similar to the one found in VirtualBox (i.e. in VBoxSVC).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/GuestProperties/service.cpp

    r24665 r24703  
    2121 */
    2222
    23 /**
     23/** @page pg_svc_guest_properties   Guest Property HGCM Service
     24 *
    2425 * This HGCM service allows the guest to set and query values in a property
    2526 * store on the host.  The service proxies the guest requests to the service
     
    3940 */
    4041
    41 #define LOG_GROUP LOG_GROUP_HGCM
    42 
    4342/*******************************************************************************
    4443*   Header Files                                                               *
    4544*******************************************************************************/
     45#define LOG_GROUP LOG_GROUP_HGCM
    4646#include <VBox/HostServices/GuestPropertySvc.h>
    4747
    4848#include <VBox/log.h>
     49#include <iprt/asm.h>
     50#include <iprt/assert.h>
     51#include <iprt/autores.h>
     52#include <iprt/cpputils.h>
    4953#include <iprt/err.h>
    50 #include <iprt/assert.h>
     54#include <iprt/mem.h>
     55#include <iprt/req.h>
    5156#include <iprt/string.h>
    52 #include <iprt/mem.h>
    53 #include <iprt/autores.h>
     57#include <iprt/thread.h>
    5458#include <iprt/time.h>
    55 #include <iprt/cpputils.h>
    56 #include <iprt/req.h>
    57 #include <iprt/thread.h>
    5859
    5960#include <memory>  /* for auto_ptr */
     
    163164    /** Queue of outstanding property change notifications */
    164165    RTREQQUEUE *mReqQueue;
     166    /** Request that we've left pending in a call to flushNotifications. */
     167    PRTREQ mPendingDummyReq;
    165168    /** Thread for processing the request queue */
    166169    RTTHREAD mReqThread;
    167170    /** Tell the thread that it should exit */
    168     bool mfExitThread;
     171    bool volatile mfExitThread;
    169172    /** Callback function supplied by the host for notification of updates
    170173     * to properties */
     
    222225public:
    223226    explicit Service(PVBOXHGCMSVCHELPERS pHelpers)
    224         : mpHelpers(pHelpers), mfExitThread(false), mpfnHostCallback(NULL),
    225           mpvHostData(NULL)
     227        : mpHelpers(pHelpers)
     228        , mPendingDummyReq(NULL)
     229        , mfExitThread(false)
     230        , mpfnHostCallback(NULL)
     231        , mpvHostData(NULL)
    226232    {
    227233        int rc = RTReqCreateQueue(&mReqQueue);
     
    321327    int delProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGuest);
    322328    int enumProps(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     329    int flushNotifications(uint32_t cMsTimeout);
    323330    int getNotification(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms,
    324331                        VBOXHGCMSVCPARM paParms[]);
     
    350357 * @copydoc FNRTTHREAD
    351358 */
     359/* static */
    352360DECLCALLBACK(int) Service::reqThreadFn(RTTHREAD ThreadSelf, void *pvUser)
    353361{
     
    819827            rc = VERR_BUFFER_OVERFLOW;
    820828    }
     829    return rc;
     830}
     831
     832/**
     833 * Flushes the notifications.
     834 *
     835 * @returns iprt status value
     836 * @param   cMsTimeout  The timeout in milliseconds.
     837 * @thread  HGCM
     838 */
     839int Service::flushNotifications(uint32_t cMsTimeout)
     840{
     841    LogFlowThisFunc(("cMsTimeout=%RU32\n", cMsTimeout));
     842    int rc;
     843
     844#ifndef VBOX_GUEST_PROP_TEST_NOTHREAD
     845    /*
     846     * Wait for the thread to finish processing all current requests.
     847     */
     848    if (!mPendingDummyReq && !RTReqIsBusy(mReqQueue))
     849        rc = VINF_SUCCESS;
     850    else
     851    {
     852        if (!mPendingDummyReq)
     853            rc = RTReqCallEx(mReqQueue, &mPendingDummyReq, 0 /*cMillies*/, RTREQFLAGS_VOID, (PFNRT)reqVoid, 0);
     854        else
     855            rc = VERR_TIMEOUT;
     856        if (rc == VERR_TIMEOUT)
     857            rc = RTReqWait(mPendingDummyReq, cMsTimeout);
     858        if (RT_SUCCESS(rc))
     859        {
     860            RTReqFree(mPendingDummyReq);
     861            mPendingDummyReq = NULL;
     862        }
     863    }
     864#else
     865    NOREF(cMsTimeout);
     866    rc = VINF_SUCCESS;
     867#endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */
     868
    821869    return rc;
    822870}
     
    10951143 */
    10961144/* static */
    1097 int Service::reqNotify(PFNHGCMSVCEXT pfnCallback, void *pvData,
    1098                        char *pszName, char *pszValue, uint32_t u32TimeHigh,
    1099                        uint32_t u32TimeLow, char *pszFlags)
     1145DECLCALLBACK(int) Service::reqNotify(PFNHGCMSVCEXT pfnCallback, void *pvData,
     1146                                     char *pszName, char *pszValue, uint32_t u32TimeHigh,
     1147                                     uint32_t u32TimeLow, char *pszFlags)
    11001148{
    11011149    LogFlowFunc (("pfnCallback=%p, pvData=%p, pszName=%p, pszValue=%p, u32TimeHigh=%u, u32TimeLow=%u, pszFlags=%p\n", pfnCallback, pvData, pszName, pszValue, u32TimeHigh, u32TimeLow, pszFlags));
     
    12471295                break;
    12481296
     1297            /* The host wishes to flush all pending notification */
     1298            case FLUSH_NOTIFICATIONS_HOST:
     1299                LogFlowFunc(("FLUSH_NOTIFICATIONS_HOST\n"));
     1300                if (cParms == 1)
     1301                {
     1302                    uint32_t cMsTimeout;
     1303                    rc = paParms[0].getUInt32(&cMsTimeout);
     1304                    if (RT_SUCCESS(rc))
     1305                        rc = flushNotifications(cMsTimeout);
     1306                }
     1307                else
     1308                    rc = VERR_INVALID_PARAMETER;
     1309                break;
     1310
    12491311            default:
    12501312                rc = VERR_NOT_SUPPORTED;
     
    12641326{
    12651327    int rc = VINF_SUCCESS;
    1266     unsigned count = 0;
    1267 
    1268     mfExitThread = true;
     1328
     1329    ASMAtomicWriteBool(&mfExitThread, true);
     1330
    12691331#ifndef VBOX_GUEST_PROP_TEST_NOTHREAD
     1332    /*
     1333     * Send a dummy request to the thread so it is forced out of the loop and
     1334     * notice that the exit flag is set.  Give up waiting after 5 mins.
     1335     * We call flushNotifications first to try clean up any pending request.
     1336     */
     1337    flushNotifications(120*1000);
     1338
    12701339    rc = RTReqCallEx(mReqQueue, NULL, 0, RTREQFLAGS_NO_WAIT, (PFNRT)reqVoid, 0);
    12711340    if (RT_SUCCESS(rc))
     1341    {
     1342        unsigned count = 0;
    12721343        do
    12731344        {
     
    12761347            Assert(RT_SUCCESS(rc) || ((VERR_TIMEOUT == rc) && (count != 5)));
    12771348        } while ((VERR_TIMEOUT == rc) && (count < 300));
     1349    }
    12781350#endif /* VBOX_GUEST_PROP_TEST_NOTHREAD not defined */
    12791351    if (RT_SUCCESS(rc))
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