VirtualBox

Changeset 29220 in vbox


Ignore:
Timestamp:
May 7, 2010 3:09:53 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
61300
Message:

Guest Control/Main/HostService: Deal with stale clients, avoid deadlocks when doing massive output traffic.

Location:
trunk/src/VBox
Files:
3 edited

Legend:

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

    r29003 r29220  
    2828
    2929#include <VBox/log.h>
    30 #include <iprt/asm.h>
     30#include <iprt/asm.h> /* For ASMBreakpoint(). */
    3131#include <iprt/assert.h>
    3232#include <iprt/cpp/autores.h>
     
    6565struct GuestCall
    6666{
     67    /** Client ID; a client can have multiple handles! */
     68    uint32_t mClientID;
    6769    /** The call handle */
    6870    VBOXHGCMCALLHANDLE mHandle;
     
    7375
    7476    /** The standard constructor */
    75     GuestCall() : mHandle(0), mParms(NULL), mNumParms(0) {}
     77    GuestCall() : mClientID(0), mHandle(0), mParms(NULL), mNumParms(0) {}
    7678    /** The normal contructor */
    77     GuestCall(VBOXHGCMCALLHANDLE aHandle, VBOXHGCMSVCPARM aParms[], int cParms)
    78               : mHandle(aHandle), mParms(aParms), mNumParms(cParms) {}
     79    GuestCall(uint32_t aClientID, VBOXHGCMCALLHANDLE aHandle,
     80              VBOXHGCMSVCPARM aParms[], uint32_t cParms)
     81              : mClientID(aClientID), mHandle(aHandle), mParms(aParms), mNumParms(cParms) {}
    7982};
    8083/** The guest call list type */
    81 typedef std::list <GuestCall> CallList;
     84typedef std::list< GuestCall > CallList;
     85typedef std::list< GuestCall >::iterator CallListIter;
     86typedef std::list< GuestCall >::const_iterator CallListIterConst;
    8287
    8388/**
     
    9196    /** HGCM helper functions. */
    9297    PVBOXHGCMSVCHELPERS mpHelpers;
    93     /** @todo we should have classes for thread and request handler thread */
    94     /** Queue of outstanding property change notifications */
    95     RTREQQUEUE *mReqQueue;
    96     /** Request that we've left pending in a call to flushNotifications. */
    97     PRTREQ mPendingDummyReq;
    98     /** Thread for processing the request queue */
    99     RTTHREAD mReqThread;
    100     /** Tell the thread that it should exit */
    101     bool volatile mfExitThread;
    10298    /** Callback function supplied by the host for notification of updates
    10399     * to properties */
     
    113109    explicit Service(PVBOXHGCMSVCHELPERS pHelpers)
    114110        : mpHelpers(pHelpers)
    115         , mPendingDummyReq(NULL)
    116         , mfExitThread(false)
    117111        , mpfnHostCallback(NULL)
    118112        , mpvHostData(NULL)
    119113    {
    120         int rc = RTReqCreateQueue(&mReqQueue);
    121 #ifndef VBOX_GUEST_CTRL_TEST_NOTHREAD
    122         if (RT_SUCCESS(rc))
    123             rc = RTThreadCreate(&mReqThread, reqThreadFn, this, 0,
    124                                 RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
    125                                 "GuestCtrlReq");
    126 #endif
    127         if (RT_FAILURE(rc))
    128             throw rc;
    129114    }
    130115
     
    231216    int paramBufferAssign(PVBOXGUESTCTRPARAMBUFFER pBuf, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    232217    int prepareExecute(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    233     static DECLCALLBACK(int) reqThreadFn(RTTHREAD ThreadSelf, void *pvUser);
    234218    int clientConnect(uint32_t u32ClientID, void *pvClient);
    235219    int clientDisconnect(uint32_t u32ClientID, void *pvClient);
    236220    int sendHostCmdToGuest(HostCmd *pCmd, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    237     int retrieveNextHostCmd(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     221    int retrieveNextHostCmd(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    238222    int notifyHost(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    239223    int processHostCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     
    246230
    247231
    248 /**
    249  * Thread function for processing the request queue
    250  * @copydoc FNRTTHREAD
    251  */
    252 /* static */
    253 DECLCALLBACK(int) Service::reqThreadFn(RTTHREAD ThreadSelf, void *pvUser)
    254 {
    255     SELF *pSelf = reinterpret_cast<SELF *>(pvUser);
    256     while (!pSelf->mfExitThread)
    257         RTReqProcess(pSelf->mReqQueue, RT_INDEFINITE_WAIT);
    258     return VINF_SUCCESS;
    259 }
    260 
    261232/** @todo Write some nice doc headers! */
    262233/* Stores a HGCM request in an internal buffer (pEx). Needs to be freed later using execBufferFree(). */
     
    265236    AssertPtr(pBuf);
    266237    int rc = VINF_SUCCESS;
     238
     239    /* Paranoia. */
     240    if (cParms > 256)
     241        cParms = 256;
    267242
    268243    /*
     
    392367{
    393368    LogFlowFunc(("Client (%ld) disconnected\n", u32ClientID));
     369    /*
     370     * Throw out all stale clients.
     371     */
     372    CallListIter it = mClientList.begin();
     373    while (it != mClientList.end())
     374    {
     375        if (it->mClientID == u32ClientID)
     376            it = mClientList.erase(it);
     377        else
     378            it++;
     379    }
    394380    return VINF_SUCCESS;
    395381}
     
    424410 * defer the guest call until we have something from the host.
    425411 */
    426 int Service::retrieveNextHostCmd(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     412int Service::retrieveNextHostCmd(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle,
     413                                 uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    427414{
    428415    int rc = VINF_SUCCESS;
     
    435422    if (mHostCmds.empty()) /* If command list is empty, defer ... */
    436423    {
    437         mClientList.push_back(GuestCall(callHandle, paParms, cParms));
     424        mClientList.push_back(GuestCall(u32ClientID, callHandle, paParms, cParms));
    438425        rc = VINF_HGCM_ASYNC_EXECUTE;
    439426    }
     
    535522        if (!fProcessed)
    536523        {
    537             mHostCmds.push_back(newCmd);
    538    
     524            mHostCmds.push_back(newCmd);   
     525#if 0
    539526            /* Limit list size by deleting oldest element. */
    540527            if (mHostCmds.size() > 256) /** @todo Use a define! */
    541528                mHostCmds.pop_front();
     529#endif
    542530        }
    543531    }
     
    568556            case GUEST_GET_HOST_MSG:
    569557                LogFlowFunc(("GUEST_GET_HOST_MSG\n"));
    570                 rc = retrieveNextHostCmd(callHandle, cParms, paParms);
     558                rc = retrieveNextHostCmd(u32ClientID, callHandle, cParms, paParms);
    571559                break;
    572560
  • trunk/src/VBox/Main/GuestImpl.cpp

    r29005 r29220  
    117117    CallbackListIter it;
    118118    for (it = mCallbackList.begin(); it != mCallbackList.end(); it++)
    119         removeCtrlCallbackContext(it);
     119        destroyCtrlCallbackContext(it);
    120120
    121121    /* Clear process list. */
     
    467467    int rc = VINF_SUCCESS;
    468468
     469    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     470
    469471    AssertPtr(pData);
    470472    CallbackListIter it = getCtrlCallbackContextByID(pData->hdr.u32ContextID);
     
    473475    if (it != mCallbackList.end())
    474476    {
    475         AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    476 
    477477        PHOSTEXECCALLBACKDATA pCBData = (HOSTEXECCALLBACKDATA*)it->pvData;
    478478        AssertPtr(pCBData);
     
    581581    int rc = VINF_SUCCESS;
    582582
     583    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     584
    583585    AssertPtr(pData);
    584586    CallbackListIter it = getCtrlCallbackContextByID(pData->hdr.u32ContextID);
     
    589591        AssertPtr(pCBData);
    590592
    591         AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    592 
    593593        pCBData->u32PID = pData->u32PID;
    594594        pCBData->u32HandleId = pData->u32HandleId;
     
    601601            /* Allocate data buffer and copy it */
    602602            pCBData->pvData = RTMemAlloc(pData->cbData);
     603            pCBData->cbData = pData->cbData;
     604
    603605            AssertReturn(pCBData->pvData, VERR_NO_MEMORY);
    604606            memcpy(pCBData->pvData, pData->pvData, pData->cbData);
    605             pCBData->cbData = pData->cbData;
    606607        }
    607608        else
     
    646647}
    647648
    648 void Guest::removeCtrlCallbackContext(Guest::CallbackListIter it)
     649/* No locking here; */
     650void Guest::destroyCtrlCallbackContext(Guest::CallbackListIter it)
    649651{
    650652    LogFlowFuncEnter();
    651     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    652653    if (it->pvData)
    653654    {
     
    678679{
    679680    LogFlowFuncEnter();
    680     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    681681    uint32_t uNewContext = ASMAtomicIncU32(&mNextContextID);
    682682    if (uNewContext == UINT32_MAX)
    683683        ASMAtomicUoWriteU32(&mNextContextID, 1000);
    684684
     685    /** @todo Put this stuff into a constructor! */
    685686    CallbackContext context;
    686687    context.mContextID = uNewContext;
     
    691692    context.pProgress = pProgress;
    692693
    693     mCallbackList.push_back(context);
    694     if (mCallbackList.size() > 256) /* Don't let the container size get too big! */
     694    uint32_t nCallbacks;
     695    {
     696        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     697        mCallbackList.push_back(context);
     698        nCallbacks = mCallbackList.size();
     699    }   
     700
     701#if 0
     702    if (nCallbacks > 256) /* Don't let the container size get too big! */
    695703    {
    696704        Guest::CallbackListIter it = mCallbackList.begin();
    697         removeCtrlCallbackContext(it);
    698         mCallbackList.erase(it);
    699     }
     705        destroyCtrlCallbackContext(it);
     706        {
     707            AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     708            mCallbackList.erase(it);
     709        }
     710    }
     711#endif
    700712
    701713    LogFlowFuncLeave();
     
    823835                    paParms[i++].setUInt32(aTimeoutMS);
    824836
    825                     /* Make sure mParent is valid, so set a read lock in this scope. */
    826                     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    827 
    828                     /* Forward the information to the VMM device. */
    829                     AssertPtr(mParent);
    830                     VMMDev *vmmDev = mParent->getVMMDev();
     837                    VMMDev *vmmDev;
     838                    {
     839                        /* Make sure mParent is valid, so set the read lock while using.
     840                         * Do not keep this lock while doing the actual call, because in the meanwhile
     841                         * another thread could request a write lock which would be a bad idea ... */
     842                        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     843   
     844                        /* Forward the information to the VMM device. */
     845                        AssertPtr(mParent);
     846                        vmmDev = mParent->getVMMDev();
     847                    }
     848
    831849                    if (vmmDev)
    832850                    {
     
    10651083   
    10661084        {
    1067             /* Make sure mParent is valid, so set the read lock while using. */
    1068             AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    1069    
    1070             /* Forward the information to the VMM device. */
    1071             AssertPtr(mParent);
    1072             VMMDev *vmmDev = mParent->getVMMDev();
     1085            VMMDev *vmmDev;
     1086            {
     1087                /* Make sure mParent is valid, so set the read lock while using.
     1088                 * Do not keep this lock while doing the actual call, because in the meanwhile
     1089                 * another thread could request a write lock which would be a bad idea ... */
     1090                AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     1091       
     1092                /* Forward the information to the VMM device. */
     1093                AssertPtr(mParent);
     1094                vmmDev = mParent->getVMMDev();
     1095            }
     1096
    10731097            if (vmmDev)
    10741098            {
     
    11711195                    }
    11721196                }
     1197
     1198                {
     1199                    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1200                    destroyCtrlCallbackContext(it);
     1201                }
    11731202            }
    11741203            else /* PID lookup failed. */
  • trunk/src/VBox/Main/include/GuestImpl.h

    r28800 r29220  
    151151    CallbackListIter getCtrlCallbackContextByID(uint32_t u32ContextID);
    152152    GuestProcessIter getProcessByPID(uint32_t u32PID);
    153     void removeCtrlCallbackContext(CallbackListIter it);
     153    void destroyCtrlCallbackContext(CallbackListIter it);
    154154    uint32_t addCtrlCallbackContext(eVBoxGuestCtrlCallbackType enmType, void *pvData, uint32_t cbData, Progress* pProgress);
    155155# endif
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