VirtualBox

Changeset 29785 in vbox for trunk/src/VBox/HostServices


Ignore:
Timestamp:
May 25, 2010 1:30:45 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
61989
Message:

Guest Control: More stable when client is crashing/aborting in an unusual way.

File:
1 edited

Legend:

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

    r29438 r29785  
    4848
    4949/**
    50  * Structure for holding a buffered host command
     50 * Structure for holding all clients with their
     51 * generated host contexts. This is necessary for
     52 * mainting the relationship between a client and its context IDs.
     53 */
     54struct ClientContexts
     55{
     56    /** This client ID. */
     57    uint32_t mClientID;
     58    /** The list of contexts a client is assigned to. */
     59    std::list< uint32_t > mContextList;
     60
     61    /** The normal contructor. */
     62    ClientContexts(uint32_t aClientID)
     63                   : mClientID(aClientID) {}
     64};
     65/** The client list + iterator type */
     66typedef std::list< ClientContexts > ClientContextsList;
     67typedef std::list< ClientContexts >::iterator ClientContextsListIter;
     68typedef std::list< ClientContexts >::const_iterator ClientContextsListIterConst;
     69
     70/**
     71 * Structure for holding a buffered host command.
    5172 */
    5273struct HostCmd
    5374{
     75    /** The context ID this command belongs to. Will be extracted
     76      * from the HGCM parameters. */
     77    uint32_t mContextID;
    5478    /** Dynamic structure for holding the HGCM parms */
    55     VBOXGUESTCTRPARAMBUFFER parmBuf;
     79    VBOXGUESTCTRPARAMBUFFER mParmBuf;
     80
     81    /** The standard contructor. */
     82    HostCmd() : mContextID(0) {}
    5683};
    5784/** The host cmd list + iterator type */
     
    6188
    6289/**
    63  * Structure for holding an uncompleted guest call
     90 * Structure for holding an uncompleted guest call.
    6491 */
    6592struct GuestCall
     
    74101    uint32_t mNumParms;
    75102
    76     /** The standard constructor */
     103    /** The standard contructor. */
    77104    GuestCall() : mClientID(0), mHandle(0), mParms(NULL), mNumParms(0) {}
    78     /** The normal contructor */
     105    /** The normal contructor. */
    79106    GuestCall(uint32_t aClientID, VBOXHGCMCALLHANDLE aHandle,
    80107              VBOXHGCMSVCPARM aParms[], uint32_t cParms)
     
    92119{
    93120private:
    94     /** Type definition for use in callback functions */
     121    /** Type definition for use in callback functions. */
    95122    typedef Service SELF;
    96123    /** HGCM helper functions. */
    97124    PVBOXHGCMSVCHELPERS mpHelpers;
    98     /** Callback function supplied by the host for notification of updates
    99      * to properties */
     125    /*
     126     * Callback function supplied by the host for notification of updates
     127     * to properties.
     128     */
    100129    PFNHGCMSVCEXT mpfnHostCallback;
    101     /** User data pointer to be supplied to the host callback function */
     130    /** User data pointer to be supplied to the host callback function. */
    102131    void *mpvHostData;
    103     /** The deferred calls list */
     132    /** The deferred calls list. */
    104133    CallList mClientList;
    105     /** The host command list */
     134    /** The host command list. */
    106135    HostCmdList mHostCmds;
     136    /** Client contexts list. */
     137    ClientContextsList mClientContextsList;
    107138
    108139public:
     
    368399{
    369400    LogFlowFunc(("Client (%ld) disconnected\n", u32ClientID));
     401
    370402    /*
    371403     * Throw out all stale clients.
    372404     */
    373     CallListIter it = mClientList.begin();
    374     while (it != mClientList.end())
     405    int rc = VINF_SUCCESS;
     406
     407    ClientContextsListIter it = mClientContextsList.begin();
     408    while (   it != mClientContextsList.end()
     409           && RT_SUCCESS(rc))
    375410    {
    376411        if (it->mClientID == u32ClientID)
    377             it = mClientList.erase(it);
     412        {
     413            std::list< uint32_t >::iterator itContext = it->mContextList.begin();
     414            while (   itContext != it->mContextList.end()
     415                   && RT_SUCCESS(rc))
     416            {
     417                LogFlowFunc(("Notifying host context %u of disconnect ...\n", (*itContext)));
     418
     419                /*
     420                 * Notify the host that clients with u32ClientID are no longer
     421                 * around and need to be cleaned up (canceling waits etc).
     422                 */
     423                if (mpfnHostCallback)
     424                {
     425                    CALLBACKDATACLIENTDISCONNECTED data;
     426                    data.hdr.u32Magic = CALLBACKDATAMAGICCLIENTDISCONNECTED;
     427                    data.hdr.u32ContextID = (*itContext);
     428                    rc = mpfnHostCallback(mpvHostData, GUEST_DISCONNECTED, (void *)(&data), sizeof(data));
     429                    if (RT_FAILURE(rc))
     430                        LogFlowFunc(("Notification of host context %u failed with %Rrc\n", rc));
     431                }
     432                itContext++;
     433            }
     434            it = mClientContextsList.erase(it);
     435        }
    378436        else
    379437            it++;
    380438    }
    381     return VINF_SUCCESS;
     439    return rc;
    382440}
    383441
     
    388446 
    389447    /* Sufficient parameter space? */
    390     if (pCmd->parmBuf.uParmCount > cParms)
    391     {
    392         paParms[0].setUInt32(pCmd->parmBuf.uMsg);       /* Message ID */
    393         paParms[1].setUInt32(pCmd->parmBuf.uParmCount); /* Required parameters for message */
     448    if (pCmd->mParmBuf.uParmCount > cParms)
     449    {
     450        paParms[0].setUInt32(pCmd->mParmBuf.uMsg);       /* Message ID */
     451        paParms[1].setUInt32(pCmd->mParmBuf.uParmCount); /* Required parameters for message */
    394452       
    395453        /*
     
    402460    else
    403461    {
    404         rc = paramBufferAssign(&pCmd->parmBuf, cParms, paParms);
     462        rc = paramBufferAssign(&pCmd->mParmBuf, cParms, paParms);
    405463    }
    406464    return rc;
     
    415473{
    416474    int rc = VINF_SUCCESS;
     475
     476    /*
     477     * Lookup client in our list so that we can assign the context ID of
     478     * a command to that client.
     479     */
     480    std::list< ClientContexts >::reverse_iterator it = mClientContextsList.rbegin();
     481    while (it != mClientContextsList.rend())
     482    {
     483        if (it->mClientID == u32ClientID)
     484            break;
     485        it++;
     486    }
     487
     488    /* Not found? Add client to list. */
     489    if (it == mClientContextsList.rend())
     490    {
     491        mClientContextsList.push_back(ClientContexts(u32ClientID));
     492        it = mClientContextsList.rbegin();
     493    }
     494    Assert(it != mClientContextsList.rend());
    417495
    418496    /*
     
    435513         if (RT_SUCCESS(rc))
    436514         {
    437              /* Only if the guest really got and understood the message
    438               * remove it from the list. */
    439              paramBufferFree(&curCmd.parmBuf);
     515             /* Remember which client processes which context (for
     516              * later reference & cleanup). */
     517             Assert(curCmd.mContextID > 0);
     518             it->mContextList.push_back(curCmd.mContextID);
     519
     520             /* Only if the guest really got and understood the message remove it from the list. */
     521             paramBufferFree(&curCmd.mParmBuf);
    440522             mHostCmds.pop_front();
    441523         }
     
    444526}
    445527
     528/*
     529 * Client asks itself (in another thread) to cancel all pending waits which are blocking the client
     530 * from shutting down / doing something else.
     531 */
    446532int Service::cancelPendingWaits(uint32_t u32ClientID)
    447533{
     
    454540            if (it->mNumParms >= 2)
    455541            {
    456                 it->mParms[0].setUInt32(GETHOSTMSG_EXEC_HOST_CANCEL_WAIT); /* Message ID */
    457                 it->mParms[1].setUInt32(0);                                /* Required parameters for message */
     542                it->mParms[0].setUInt32(GETHOSTMSG_EXEC_HOST_CANCEL_WAIT); /* Message ID. */
     543                it->mParms[1].setUInt32(0);                                /* Required parameters for message. */
    458544            }             
    459545            if (mpHelpers)
     
    475561        && cParms    == 5)
    476562    {
    477         HOSTEXECCALLBACKDATA data;
    478         data.hdr.u32Magic = HOSTEXECCALLBACKDATAMAGIC;
     563        CALLBACKDATAEXECSTATUS data;
     564        data.hdr.u32Magic = CALLBACKDATAMAGICEXECSTATUS;
    479565        paParms[0].getUInt32(&data.hdr.u32ContextID);
    480566
     
    491577             && cParms    == 5)
    492578    {
    493         HOSTEXECOUTCALLBACKDATA data;
    494         data.hdr.u32Magic = HOSTEXECOUTCALLBACKDATAMAGIC;
     579        CALLBACKDATAEXECOUT data;
     580        data.hdr.u32Magic = CALLBACKDATAMAGICEXECOUT;
    495581        paParms[0].getUInt32(&data.hdr.u32ContextID);
    496582
     
    515601
    516602    HostCmd newCmd;
     603    rc = paramBufferAllocate(&newCmd.mParmBuf, eFunction, cParms, paParms);
     604    if (   RT_SUCCESS(rc)
     605        && newCmd.mParmBuf.uParmCount > 0)
     606    {
     607        /*
     608         * Assume that the context ID *always* is the first parameter,
     609         * assign the context ID to the command.
     610         */
     611        newCmd.mParmBuf.pParms[0].getUInt32(&newCmd.mContextID);
     612        Assert(newCmd.mContextID > 0);
     613    }
     614
    517615    bool fProcessed = false;
    518     rc = paramBufferAllocate(&newCmd.parmBuf, eFunction, cParms, paParms);
    519616    if (RT_SUCCESS(rc))
    520617    {
     
    539636            else /* If command was understood by the client, free and remove from host commands list. */
    540637            {
    541                 paramBufferFree(&newCmd.parmBuf);
     638                paramBufferFree(&newCmd.mParmBuf);
    542639                fProcessed = true;
    543640            }
     
    668765    HostCmdListIter it;
    669766    for (it = mHostCmds.begin(); it != mHostCmds.end(); it++)
    670         paramBufferFree(&it->parmBuf);
     767        paramBufferFree(&it->mParmBuf);
    671768    mHostCmds.clear();
    672769
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