VirtualBox

Changeset 22686 in vbox


Ignore:
Timestamp:
Sep 1, 2009 10:09:14 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
51799
Message:

VBoxManage: guestproperty wait fixes, esp. for Mac OS X.

Location:
trunk/src/VBox/Frontends/VBoxManage
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp

    r22562 r22686  
    18291829     * after the session is closed) */
    18301830
    1831 #ifdef USE_XPCOM_QUEUE
     1831#ifdef VBOX_WITH_XPCOM
    18321832    nsCOMPtr<nsIEventQueue> eventQ;
    18331833    NS_GetMainEventQ(getter_AddRefs(eventQ));
    18341834#endif
    18351835
    1836 #ifdef USE_XPCOM_QUEUE
     1836#ifdef VBOX_WITH_XPCOM
    18371837    HandlerArg handlerArg = { 0, NULL, eventQ, virtualBox, session };
    18381838#else
     
    19171917    session->Close();
    19181918
    1919 #ifdef USE_XPCOM_QUEUE
     1919#ifdef VBOX_WITH_XPCOM
    19201920    eventQ->ProcessPendingEvents();
    19211921#endif
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h

    r22562 r22686  
    108108    char **argv;
    109109
    110 #ifdef USE_XPCOM_QUEUE
     110#ifdef VBOX_WITH_XPCOM
    111111    nsCOMPtr<nsIEventQueue> eventQ;
    112112#endif
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp

    r22305 r22686  
    3535
    3636#include <VBox/log.h>
     37#include <iprt/asm.h>
     38#include <iprt/semaphore.h>
    3739#include <iprt/stream.h>
     40#include <iprt/string.h>
     41#include <iprt/time.h>
    3842#include <iprt/thread.h>
    39 #include <iprt/time.h>
    4043
    4144#ifdef USE_XPCOM_QUEUE
    4245# include <sys/select.h>
     46# include <errno.h>
    4347#endif
    4448
     
    5963        refcnt = 0;
    6064#endif
    61     }
    62 
    63     virtual ~GuestPropertyCallback() {}
     65#ifndef USE_XPCOM_QUEUE
     66        int rc = RTSemEventMultiCreate(&mhEvent);
     67        if (RT_FAILURE(rc))
     68            mhEvent = NIL_RTSEMEVENTMULTI;
     69#endif
     70    }
     71
     72    virtual ~GuestPropertyCallback()
     73    {
     74#ifndef USE_XPCOM_QUEUE
     75        RTSemEventMultiDestroy(mhEvent);
     76        mhEvent = NIL_RTSEMEVENTMULTI;
     77#endif
     78    }
    6479
    6580#ifndef VBOX_WITH_XPCOM
     
    150165                                     IN_BSTR flags)
    151166    {
    152         HRESULT rc = S_OK;
    153167        Utf8Str utf8Name(name);
    154168        Guid uuid(machineId);
    155         if (   SUCCEEDED (rc)
    156             && uuid == mUuid
     169        if (   uuid == mUuid
    157170            && RTStrSimplePatternMultiMatch(mPatterns, RTSTR_MAX,
    158171                                            utf8Name.raw(), RTSTR_MAX, NULL))
    159172        {
    160             RTPrintf("Name: %lS, value: %lS, flags: %lS\n", name, value,
    161                      flags);
    162             mSignalled = true;
    163         }
    164         return rc;
    165     }
    166 
    167     bool Signalled(void) { return mSignalled; }
     173            RTPrintf("Name: %lS, value: %lS, flags: %lS\n", name, value, flags);
     174            ASMAtomicWriteBool(&mSignalled, true);
     175#ifndef USE_XPCOM_QUEUE
     176            int rc = RTSemEventMultiSignal(mhEvent);
     177            AssertRC(rc);
     178#endif
     179        }
     180        return S_OK;
     181    }
     182
     183    bool Signalled(void) const
     184    {
     185        return mSignalled;
     186    }
     187
     188#ifndef USE_XPCOM_QUEUE
     189    /** Wrapper around RTSemEventMultiWait. */
     190    int wait(uint32_t cMillies)
     191    {
     192        return RTSemEventMultiWait(mhEvent, cMillies);
     193    }
     194#endif
    168195
    169196private:
    170     bool mSignalled;
     197    bool volatile mSignalled;
    171198    const char *mPatterns;
    172199    Guid mUuid;
     
    174201    long refcnt;
    175202#endif
    176 
     203#ifndef USE_XPCOM_QUEUE
     204    /** Event semaphore to wait on. */
     205    RTSEMEVENTMULTI mhEvent;
     206#endif
    177207};
    178208
    179209#ifdef VBOX_WITH_XPCOM
    180210NS_DECL_CLASSINFO(GuestPropertyCallback)
    181 NS_IMPL_ISUPPORTS1_CI(GuestPropertyCallback, IVirtualBoxCallback)
     211NS_IMPL_THREADSAFE_ISUPPORTS1_CI(GuestPropertyCallback, IVirtualBoxCallback)
    182212#endif /* VBOX_WITH_XPCOM */
    183213
     
    194224             "\n");
    195225    RTPrintf("VBoxManage guestproperty    wait <vmname>|<uuid> <patterns>\n"
    196              "                            [--timeout <timeout>]\n"
     226             "                            [--timeout <milliseconds>] [--fail-on-timeout]\n"
    197227             "\n");
    198228}
     
    395425     * Handle arguments
    396426     */
    397     const char *pszPatterns = NULL;
    398     uint32_t u32Timeout = RT_INDEFINITE_WAIT;
    399     bool usageOK = true;
     427    bool        fFailOnTimeout = false;
     428    const char *pszPatterns    = NULL;
     429    uint32_t    cMsTimeout     = RT_INDEFINITE_WAIT;
     430    bool        usageOK        = true;
    400431    if (a->argc < 2)
    401432        usageOK = false;
     
    418449        {
    419450            if (   i + 1 >= a->argc
    420                 || RTStrToUInt32Full(a->argv[i + 1], 10, &u32Timeout)
    421                        != VINF_SUCCESS
    422                )
     451                || RTStrToUInt32Full(a->argv[i + 1], 10, &cMsTimeout) != VINF_SUCCESS)
    423452                usageOK = false;
    424453            else
    425454                ++i;
    426455        }
     456        else if (!strcmp(a->argv[i], "--fail-on-timeout"))
     457            fFailOnTimeout = true;
    427458        else
    428459            usageOK = false;
     
    433464    /*
    434465     * Set up the callback and wait.
     466     *
     467     * The waiting is done is 1 sec at the time since there there are races
     468     * between the callback and us going to sleep.  This also guards against
     469     * neglecting XPCOM event queues as well as any select timeout restrictions.
    435470     */
    436471    Bstr uuid;
    437472    machine->COMGETTER(Id)(uuid.asOutParam());
    438     GuestPropertyCallback* cbImpl = new GuestPropertyCallback(pszPatterns, uuid);
     473    GuestPropertyCallback *cbImpl = new GuestPropertyCallback(pszPatterns, uuid);
    439474    ComPtr<IVirtualBoxCallback> callback;
    440     rc = createCallbackWrapper((IVirtualBoxCallback*)cbImpl, callback.asOutParam());
     475    rc = createCallbackWrapper((IVirtualBoxCallback *)cbImpl, callback.asOutParam());
    441476    if (FAILED(rc))
     477    {
     478        RTPrintf("Error creating callback wrapper: %Rhrc\n", rc);
    442479        return 1;
    443     a->virtualBox->RegisterCallback (callback);
    444     bool stop = false;
     480    }
     481    a->virtualBox->RegisterCallback(callback);
     482
    445483#ifdef USE_XPCOM_QUEUE
    446     int max_fd = a->eventQ->GetEventQueueSelectFD();
    447 #endif
    448     for (; !stop && u32Timeout > 0; u32Timeout -= RT_MIN(u32Timeout, 1000))
    449     {
     484    int const       fdQueue      = a->eventQ->GetEventQueueSelectFD();
     485#endif
     486    uint64_t const  StartMilliTS = RTTimeMilliTS();
     487    for (;;)
     488    {
     489#ifdef VBOX_WITH_XPCOM
     490        /* Process pending XPCOM events. */
     491        a->eventQ->ProcessPendingEvents();
     492#endif
     493
     494        /* Signalled? */
     495        if (cbImpl->Signalled())
     496            break;
     497
     498        /* Figure out how much we have left to wait and if we've timed out already. */
     499        uint32_t cMsLeft;
     500        if (cMsTimeout == RT_INDEFINITE_WAIT)
     501            cMsLeft = RT_INDEFINITE_WAIT;
     502        else
     503        {
     504            uint64_t cMsElapsed = RTTimeMilliTS() - StartMilliTS;
     505            if (cMsElapsed >= cMsTimeout)
     506                break; /* timeout */
     507            cMsLeft = cMsTimeout - (uint32_t)cMsElapsed;
     508        }
     509
     510        /* Wait in a platform specific manner. */
    450511#ifdef USE_XPCOM_QUEUE
    451         int prc;
    452512        fd_set fdset;
     513        FD_ZERO(&fdset);
     514        FD_SET(fdQueue, &fdset);
    453515        struct timeval tv;
    454         FD_ZERO (&fdset);
    455         FD_SET(max_fd, &fdset);
    456         tv.tv_sec = RT_MIN(u32Timeout, 1000);
    457         tv.tv_usec = u32Timeout > 1000 ? 0 : u32Timeout * 1000;
    458         RTTIMESPEC TimeNow;
    459         uint64_t u64Time = RTTimeSpecGetMilli(RTTimeNow(&TimeNow));
    460         prc = select(max_fd + 1, &fdset, NULL, NULL, &tv);
     516        if (    cMsLeft == RT_INDEFINITE_WAIT
     517            ||  cMsLeft >= 1000)
     518        {
     519            tv.tv_sec = 1;
     520            tv.tv_usec = 0;
     521        }
     522        else
     523        {
     524            tv.tv_sec = 0;
     525            tv.tv_usec = cMsLeft * 1000;
     526        }
     527        int prc = select(fdQueue + 1, &fdset, NULL, NULL, &tv);
    461528        if (prc == -1)
    462529        {
    463             RTPrintf("Error waiting for event.\n");
    464             stop = true;
    465         }
    466         else if (prc != 0)
    467         {
    468             uint64_t u64NextTime = RTTimeSpecGetMilli(RTTimeNow(&TimeNow));
    469             u32Timeout += (uint32_t)(u64Time + 1000 - u64NextTime);
    470             a->eventQ->ProcessPendingEvents();
    471             if (cbImpl->Signalled())
    472                 stop = true;
     530            RTPrintf("Error waiting for event: %s (%d)\n", strerror(errno), errno);
     531            break;
    473532        }
    474533#else  /* !USE_XPCOM_QUEUE */
    475         /** @todo Use a semaphore.  But I currently don't have a Windows system
    476          * running to test on. */
    477         /**@todo r=bird: get to it!*/
    478         RTThreadSleep(RT_MIN(1000, u32Timeout));
    479         if (cbImpl->Signalled())
    480             stop = true;
     534/** @todo make this faster on Mac OS X (and possible Windows+OS/2 too), we should probably use WaitNextEvent() to wait here. */
     535        int vrc = cbImpl->wait(RT_MIN(cMsLeft, 1000));
     536        if (    vrc != VERR_TIMEOUT
     537            &&  RT_FAILURE(vrc))
     538        {
     539            RTPrintf("Error waiting for event: %Rrc\n", vrc);
     540            break;
     541        }
    481542#endif /* !USE_XPCOM_QUEUE */
    482     }
    483 
    484     /*
    485      * Clean up the callback.
     543    } /* for (;;) */
     544
     545    /*
     546     * Clean up the callback and report timeout.
    486547     */
    487548    a->virtualBox->UnregisterCallback(callback);
     549
     550    int rcRet = 0;
    488551    if (!cbImpl->Signalled())
     552    {
    489553        RTPrintf("Time out or interruption while waiting for a notification.\n");
    490     /*
    491      * Done.
    492      */
    493     return 0;
     554        if (fFailOnTimeout)
     555            rcRet = 2;
     556    }
     557    return rcRet;
    494558}
    495559
     
    522586    return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");
    523587}
     588
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