VirtualBox

Changeset 39906 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jan 30, 2012 12:50:03 PM (13 years ago)
Author:
vboxsync
Message:

GuestCtrl/VBoxService: Added active/inactive guest process thread handling, put process starting parameters into a struct, shortcut for handling 0-byte write requests.

Location:
trunk/src/VBox/Additions/common/VBoxService
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp

    r39874 r39906  
    4646 *  the maximum number of processes is unlimited. */
    4747static uint32_t             g_GuestControlProcsMaxKept = 25;
    48 /** List of guest control threads (VBOXSERVICECTRLTHREAD). */
    49 static RTLISTANCHOR         g_GuestControlThreads;
     48/** List of active guest control threads (VBOXSERVICECTRLTHREAD). */
     49static RTLISTANCHOR         g_GuestControlThreadsActive;
     50/** List of inactive guest control threads (VBOXSERVICECTRLTHREAD). */
     51static RTLISTANCHOR         g_GuestControlThreadsInactive;
    5052/** Critical section protecting g_GuestControlExecThreads. */
    5153static RTCRITSECT           g_GuestControlThreadsCritSect;
     
    5658*******************************************************************************/
    5759/** @todo Shorten "VBoxServiceControl" to "gstsvcCntl". */
     60static int VBoxServiceControlReapThreads(void);
    5861static int VBoxServiceControlStartAllowed(bool *pbAllowed);
    5962static int VBoxServiceControlHandleCmdStartProc(uint32_t u32ClientId, uint32_t uNumParms);
     
    135138        VBoxServiceVerbose(3, "Control: Service client ID: %#x\n", g_GuestControlSvcClientID);
    136139
    137         /* Init thread list. */
    138         RTListInit(&g_GuestControlThreads);
     140        /* Init thread lists. */
     141        RTListInit(&g_GuestControlThreadsActive);
     142        RTListInit(&g_GuestControlThreadsInactive);
     143
     144        /* Init critical section for protecting the thread lists. */
    139145        rc = RTCritSectInit(&g_GuestControlThreadsCritSect);
    140146        AssertRC(rc);
     
    237243 *
    238244 * @returns IPRT status code.
    239  * @param   idClient        The HGCM client session ID.
     245 * @param   uClientID       The HGCM client session ID.
    240246 * @param   cParms          The number of parameters the host is offering.
    241247 */
    242 static int VBoxServiceControlHandleCmdStartProc(uint32_t idClient, uint32_t cParms)
    243 {
    244     uint32_t    uContextID;
    245     char        szCmd[_1K];
    246     uint32_t    uFlags;
    247     char        szArgs[_1K];
    248     uint32_t    cArgs;
    249     char        szEnv[_64K];
    250     uint32_t    cbEnv = sizeof(szEnv);
    251     uint32_t    cEnvVars;
    252     char        szUser[128];
    253     char        szPassword[128];
    254     uint32_t    uTimeLimitMS;
    255 
    256 #if 0 /* for valgrind */
    257     RT_ZERO(szCmd);
    258     RT_ZERO(szArgs);
    259     RT_ZERO(szEnv);
    260     RT_ZERO(szUser);
    261     RT_ZERO(szPassword);
    262 #endif
     248static int VBoxServiceControlHandleCmdStartProc(uint32_t uClientID, uint32_t cParms)
     249{
     250    uint32_t uContextID = 0;
    263251
    264252    int rc;
     
    266254    if (cParms == 11)
    267255    {
    268         rc = VbglR3GuestCtrlExecGetHostCmdExec(idClient,
     256        VBOXSERVICECTRLPROCESS proc;
     257        RT_ZERO(proc);
     258
     259        rc = VbglR3GuestCtrlExecGetHostCmdExec(uClientID,
    269260                                               cParms,
    270261                                               &uContextID,
    271262                                               /* Command */
    272                                                szCmd,      sizeof(szCmd),
     263                                               proc.szCmd,      sizeof(proc.szCmd),
    273264                                               /* Flags */
    274                                                &uFlags,
     265                                               &proc.uFlags,
    275266                                               /* Arguments */
    276                                                szArgs,     sizeof(szArgs), &cArgs,
     267                                               proc.szArgs,     sizeof(proc.szArgs), &proc.uNumArgs,
    277268                                               /* Environment */
    278                                                szEnv, &cbEnv, &cEnvVars,
     269                                               proc.szEnv, &proc.cbEnv, &proc.uNumEnvVars,
    279270                                               /* Credentials */
    280                                                szUser,     sizeof(szUser),
    281                                                szPassword, sizeof(szPassword),
     271                                               proc.szUser,     sizeof(proc.szUser),
     272                                               proc.szPassword, sizeof(proc.szPassword),
    282273                                               /* Timelimit */
    283                                                &uTimeLimitMS);
     274                                               &proc.uTimeLimitMS);
    284275        if (RT_SUCCESS(rc))
    285276        {
    286277            VBoxServiceVerbose(3, "Control: Request to start process szCmd=%s, uFlags=0x%x, szArgs=%s, szEnv=%s, szUser=%s, uTimeout=%u\n",
    287                                szCmd, uFlags, cArgs ? szArgs : "<None>", cEnvVars ? szEnv : "<None>", szUser, uTimeLimitMS);
     278                               proc.szCmd, proc.uFlags,
     279                               proc.uNumArgs ? proc.szArgs : "<None>",
     280                               proc.uNumEnvVars ? proc.szEnv : "<None>",
     281                               proc.szUser, proc.uTimeLimitMS);
     282
     283            rc = VBoxServiceControlReapThreads();
     284            if (RT_FAILURE(rc))
     285                VBoxServiceError("Control: Reaping stopped processes failed with rc=%Rrc\n", rc);
     286            /* Keep going. */
     287
    288288            rc = VBoxServiceControlStartAllowed(&fStartAllowed);
    289289            if (RT_SUCCESS(rc))
     
    291291                if (fStartAllowed)
    292292                {
    293                     rc = RTCritSectEnter(&g_GuestControlThreadsCritSect);
    294                     if (RT_SUCCESS(rc))
    295                     {
    296                         /** @todo Put the following params into a struct! */
    297                         PRTLISTNODE pThreadNode;
    298                         rc = VBoxServiceControlThreadStart(idClient, uContextID,
    299                                                            szCmd, uFlags, szArgs, cArgs,
    300                                                            szEnv, cbEnv, cEnvVars,
    301                                                            szUser, szPassword, uTimeLimitMS,
    302                                                            &pThreadNode);
    303                         if (RT_SUCCESS(rc))
    304                         {
    305                             /* Insert thread node into thread list. */
    306                             /*rc =*/ RTListAppend(&g_GuestControlThreads, pThreadNode);
    307                         }
    308 
    309                         int rc2 = RTCritSectLeave(&g_GuestControlThreadsCritSect);
    310                         if (RT_SUCCESS(rc))
    311                             rc = rc2;
    312                     }
     293                    rc = VBoxServiceControlThreadStart(uContextID, &proc);
    313294                }
    314295                else
     
    325306        VBoxServiceError("Control: Starting process failed with rc=%Rrc\n", rc);
    326307
    327         int rc2 = VbglR3GuestCtrlExecReportStatus(idClient, uContextID, 0 /* PID, invalid. */,
     308        int rc2 = VbglR3GuestCtrlExecReportStatus(uClientID, uContextID, 0 /* PID, invalid. */,
    328309                                                  PROC_STS_ERROR, rc,
    329310                                                  NULL /* pvData */, 0 /* cbData */);
     
    399380
    400381/**
     382 * Sets the specified guest thread to a certain list.
     383 *
     384 * @return  IPRT status code.
     385 * @param   enmList                 List to move thread to.
     386 * @param   pThread                 Thread to set inactive.
     387 */
     388int VBoxServiceControlListSet(VBOXSERVICECTRLTHREADLISTTYPE enmList,
     389                              PVBOXSERVICECTRLTHREAD pThread)
     390{
     391    AssertReturn(enmList > VBOXSERVICECTRLTHREADLIST_UNKNOWN, VERR_INVALID_PARAMETER);
     392    AssertPtrReturn(pThread, VERR_INVALID_POINTER);
     393
     394    int rc = RTCritSectEnter(&g_GuestControlThreadsCritSect);
     395    if (RT_SUCCESS(rc))
     396    {
     397        VBoxServiceVerbose(3, "Control: Setting thread (PID %u) inactive\n",
     398                           pThread->uPID);
     399
     400        PRTLISTANCHOR pAnchor = NULL;
     401        switch (enmList)
     402        {
     403            case VBOXSERVICECTRLTHREADLIST_STOPPED:
     404                pAnchor = &g_GuestControlThreadsInactive;
     405                break;
     406
     407            case VBOXSERVICECTRLTHREADLIST_RUNNING:
     408                pAnchor = &g_GuestControlThreadsActive;
     409                break;
     410
     411            default:
     412                AssertMsgFailed(("Unknown list type: %u", enmList));
     413                break;
     414        }
     415
     416        if (!pAnchor)
     417            rc = VERR_INVALID_PARAMETER;
     418
     419        if (RT_SUCCESS(rc))
     420        {
     421            if (pThread->pAnchor != NULL)
     422            {
     423                /* If thread was assigned to a list before,
     424                 * remove the thread from the old list first. */
     425                /* rc = */ RTListNodeRemove(&pThread->Node);
     426            }
     427
     428            /* Add thread to desired list. */
     429            /* rc = */ RTListAppend(pAnchor, &pThread->Node);
     430            pThread->pAnchor = pAnchor;
     431        }
     432
     433        int rc2 = RTCritSectLeave(&g_GuestControlThreadsCritSect);
     434        if (RT_SUCCESS(rc))
     435            rc = rc2;
     436    }
     437
     438    return VINF_SUCCESS;
     439}
     440
     441
     442/**
    401443 * Injects input to a specified running process.
    402444 *
     
    413455                               uint32_t *pcbWritten)
    414456{
    415     AssertPtrReturn(pvBuf, VERR_INVALID_PARAMETER);
    416     AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
     457    /* pvBuf is optional. */
     458    /* cbBuf is optional. */
    417459    /* pcbWritten is optional. */
    418460
     
    474516                         uPID, rc);
    475517    }
    476     else if (cbSize >  cbMaxBufSize)
     518    else if (cbSize > cbMaxBufSize)
    477519    {
    478520        VBoxServiceError("Control: [PID %u]: Too much input received! cbSize=%u, cbMaxBufSize=%u\n",
     
    623665
    624666/**
     667 * Reaps all inactive guest process threads.
     668 *
     669 * @return  IPRT status code.
     670 */
     671static int VBoxServiceControlReapThreads(void)
     672{
     673    int rc = RTCritSectEnter(&g_GuestControlThreadsCritSect);
     674    if (RT_SUCCESS(rc))
     675    {
     676        PVBOXSERVICECTRLTHREAD pThread =
     677            RTListGetFirst(&g_GuestControlThreadsInactive, VBOXSERVICECTRLTHREAD, Node);
     678        while (pThread)
     679        {
     680            PVBOXSERVICECTRLTHREAD pNext = RTListNodeGetNext(&pThread->Node, VBOXSERVICECTRLTHREAD, Node);
     681            bool fLast = RTListNodeIsLast(&g_GuestControlThreadsInactive, &pThread->Node);
     682
     683            int rc2 = VBoxServiceControlThreadWait(pThread, 30 * 1000 /* 30 seconds max. */);
     684            if (RT_SUCCESS(rc2))
     685            {
     686                RTListNodeRemove(&pThread->Node);
     687
     688                rc2 = VBoxServiceControlThreadFree(pThread);
     689                if (RT_FAILURE(rc2))
     690                {
     691                    VBoxServiceError("Control: Stopping guest process thread failed with rc=%Rrc\n", rc2);
     692                    if (RT_SUCCESS(rc)) /* Keep original failure. */
     693                        rc = rc2;
     694                }
     695            }
     696            else
     697                VBoxServiceError("Control: Waiting on guest process thread failed with rc=%Rrc\n", rc2);
     698            /* Keep going. */
     699
     700            if (fLast)
     701                break;
     702
     703            pThread = pNext;
     704        }
     705
     706        int rc2 = RTCritSectLeave(&g_GuestControlThreadsCritSect);
     707        if (RT_SUCCESS(rc))
     708            rc = rc2;
     709    }
     710
     711    VBoxServiceVerbose(4, "Control: Reaping threads returned with rc=%Rrc\n", rc);
     712    return rc;
     713}
     714
     715
     716/**
    625717 * Destroys all guest process threads which are still active.
    626718 */
    627 static void VBoxServiceControlDestroyThreads(void)
    628 {
    629     VBoxServiceVerbose(2, "Control: Destroying threads ...\n");
    630 
    631     /* Signal all threads that we want to shutdown. */
     719static void VBoxServiceControlShutdown(void)
     720{
     721    VBoxServiceVerbose(2, "Control: Shutting down ...\n");
     722
     723    /* Signal all threads in the active list that we want to shutdown. */
    632724    PVBOXSERVICECTRLTHREAD pThread;
    633     RTListForEach(&g_GuestControlThreads, pThread, VBOXSERVICECTRLTHREAD, Node)
    634         VBoxServiceControlThreadSignalShutdown(pThread);
    635 
    636     /* Wait for threads to shutdown and destroy thread list. */
    637     pThread = RTListGetFirst(&g_GuestControlThreads, VBOXSERVICECTRLTHREAD, Node);
     725    RTListForEach(&g_GuestControlThreadsActive, pThread, VBOXSERVICECTRLTHREAD, Node)
     726        VBoxServiceControlThreadStop(pThread);
     727
     728    /* Wait for all active threads to shutdown and destroy the active thread list. */
     729    pThread = RTListGetFirst(&g_GuestControlThreadsActive, VBOXSERVICECTRLTHREAD, Node);
    638730    while (pThread)
    639731    {
    640732        PVBOXSERVICECTRLTHREAD pNext = RTListNodeGetNext(&pThread->Node, VBOXSERVICECTRLTHREAD, Node);
    641         bool fLast = RTListNodeIsLast(&g_GuestControlThreads, &pThread->Node);
    642 
    643         int rc2 = VBoxServiceControlThreadWaitForShutdown(pThread,
    644                                                           30 * 1000 /* Wait 30 seconds max. */);
     733        bool fLast = RTListNodeIsLast(&g_GuestControlThreadsActive, &pThread->Node);
     734
     735        int rc2 = VBoxServiceControlThreadWait(pThread,
     736                                               30 * 1000 /* Wait 30 seconds max. */);
    645737        if (RT_FAILURE(rc2))
    646738            VBoxServiceError("Control: Guest process thread failed to stop; rc=%Rrc\n", rc2);
     
    652744    }
    653745
    654 #ifdef DEBUG
    655     PVBOXSERVICECTRLTHREAD pThreadCur;
    656     uint32_t cThreads = 0;
    657     RTListForEach(&g_GuestControlThreads, pThreadCur, VBOXSERVICECTRLTHREAD, Node)
    658         cThreads++;
    659     VBoxServiceVerbose(4, "Control: Guest process threads left=%u\n", cThreads);
    660 #endif
    661     AssertMsg(RTListIsEmpty(&g_GuestControlThreads),
    662               ("Guest process thread list still contains children when it should not\n"));
     746    int rc2 = VBoxServiceControlReapThreads();
     747    if (RT_FAILURE(rc2))
     748        VBoxServiceError("Control: Reaping inactive threads failed with rc=%Rrc\n", rc2);
     749
     750    AssertMsg(RTListIsEmpty(&g_GuestControlThreadsActive),
     751              ("Guest process active thread list still contains entries when it should not\n"));
     752    AssertMsg(RTListIsEmpty(&g_GuestControlThreadsInactive),
     753              ("Guest process inactive thread list still contains entries when it should not\n"));
    663754
    664755    /* Destroy critical section. */
    665756    RTCritSectDelete(&g_GuestControlThreadsCritSect);
     757
     758    VBoxServiceVerbose(2, "Control: Shutting down complete\n");
    666759}
    667760
     
    672765    VBoxServiceVerbose(3, "Control: Terminating ...\n");
    673766
    674     VBoxServiceControlDestroyThreads();
     767    VBoxServiceControlShutdown();
    675768
    676769    VBoxServiceVerbose(3, "Control: Disconnecting client ID=%u ...\n",
     
    710803        {
    711804            uint32_t uProcsRunning = 0;
    712             uint32_t uProcsStopped = 0;
    713805            PVBOXSERVICECTRLTHREAD pThread;
    714             RTListForEach(&g_GuestControlThreads, pThread, VBOXSERVICECTRLTHREAD, Node)
    715             {
    716                   VBoxServiceControlThreadActive(pThread)
    717                 ? uProcsRunning++
    718                 : uProcsStopped++;
    719             }
    720 
    721             VBoxServiceVerbose(3, "Control: Maximum served guest processes set to %u, running=%u, stopped=%u\n",
    722                                g_GuestControlProcsMaxKept, uProcsRunning, uProcsStopped);
     806            RTListForEach(&g_GuestControlThreadsActive, pThread, VBOXSERVICECTRLTHREAD, Node)
     807                uProcsRunning++;
     808
     809            VBoxServiceVerbose(3, "Control: Maximum served guest processes set to %u, running=%u\n",
     810                               g_GuestControlProcsMaxKept, uProcsRunning);
    723811
    724812            int32_t iProcsLeft = (g_GuestControlProcsMaxKept - uProcsRunning - 1);
     
    749837 * @param   uPID                        PID to search for.
    750838 */
    751 PVBOXSERVICECTRLTHREAD VBoxServiceControlGetThreadLocked(uint32_t uPID)
     839PVBOXSERVICECTRLTHREAD VBoxServiceControlLockThread(uint32_t uPID)
    752840{
    753841    PVBOXSERVICECTRLTHREAD pThread = NULL;
     
    756844    {
    757845        PVBOXSERVICECTRLTHREAD pThreadCur;
    758         RTListForEach(&g_GuestControlThreads, pThreadCur, VBOXSERVICECTRLTHREAD, Node)
     846        RTListForEach(&g_GuestControlThreadsActive, pThreadCur, VBOXSERVICECTRLTHREAD, Node)
    759847        {
    760848            if (pThreadCur->uPID == uPID)
     
    781869 * @param   pThread                 Thread to unlock.
    782870 */
    783 void VBoxServiceControlThreadUnlock(const PVBOXSERVICECTRLTHREAD pThread)
     871void VBoxServiceControlUnlockThread(const PVBOXSERVICECTRLTHREAD pThread)
    784872{
    785873    AssertPtr(pThread);
     
    812900        do
    813901        {
    814             RTListForEach(&g_GuestControlThreads, pThreadCur, VBOXSERVICECTRLTHREAD, Node)
     902            RTListForEach(&g_GuestControlThreadsActive, pThreadCur, VBOXSERVICECTRLTHREAD, Node)
    815903            {
    816904                if (pThreadCur->uPID == uPID)
     
    835923
    836924    return rc;
    837 }
    838 
    839 
    840 /**
    841  * Removes the specified guest process thread from the global thread
    842  * list.
    843  *
    844  * @return  IPRT status code.
    845  * @param   pThread             Thread to remove.
    846  */
    847 void VBoxServiceControlRemoveThread(const PVBOXSERVICECTRLTHREAD pThread)
    848 {
    849     if (!pThread)
    850         return;
    851 
    852     int rc = RTCritSectEnter(&g_GuestControlThreadsCritSect);
    853     if (RT_SUCCESS(rc))
    854     {
    855         VBoxServiceVerbose(4, "Control: Removing thread (PID: %u) from thread list\n",
    856                            pThread->uPID);
    857         RTListNodeRemove(&pThread->Node);
    858 
    859 #ifdef DEBUG
    860         PVBOXSERVICECTRLTHREAD pThreadCur;
    861         uint32_t cThreads = 0;
    862         RTListForEach(&g_GuestControlThreads, pThreadCur, VBOXSERVICECTRLTHREAD, Node)
    863             cThreads++;
    864         VBoxServiceVerbose(4, "Control: Guest process threads left=%u\n", cThreads);
    865 #endif
    866         rc = RTCritSectLeave(&g_GuestControlThreadsCritSect);
    867         AssertRC(rc);
    868     }
    869925}
    870926
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlThread.cpp

    r39896 r39906  
    4343
    4444/* Internal functions. */
    45 static int vboxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pThread);
    4645static int vboxServiceControlThreadRequestCancel(PVBOXSERVICECTRLREQUEST pThread);
    4746
     
    5251 * @param   pThread                     The thread's handle to allocate the data for.
    5352 * @param   u32ContextID                The context ID bound to this request / command.
    54  * @param   pszCmd                      Full qualified path of process to start (without arguments).
    55  * @param   uFlags                      Process execution flags.
    56  * @param   pszArgs                     String of arguments to pass to the process to start.
    57  * @param   uNumArgs                    Number of arguments specified in pszArgs.
    58  * @param   pszEnv                      String of environment variables ("FOO=BAR") to pass to the process
    59  *                                      to start.
    60  * @param   cbEnv                       Size (in bytes) of environment variables.
    61  * @param   uNumEnvVars                 Number of environment variables specified in pszEnv.
    62  * @param   pszUser                     User name (account) to start the process under.
    63  * @param   pszPassword                 Password of specified user name (account).
    64  * @param   uTimeLimitMS                Time limit (in ms) of the process' life time.
     53 @ @param   pProcess                    Process information.
    6554 */
    6655static int gstsvcCntlExecThreadInit(PVBOXSERVICECTRLTHREAD pThread,
    67                                     uint32_t u32ContextID,
    68                                     const char *pszCmd, uint32_t uFlags,
    69                                     const char *pszArgs, uint32_t uNumArgs,
    70                                     const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
    71                                     const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS)
     56                                    PVBOXSERVICECTRLPROCESS pProcess,
     57                                    uint32_t u32ContextID)
    7258{
    7359    AssertPtrReturn(pThread, VERR_INVALID_POINTER);
     60    AssertPtrReturn(pProcess, VERR_INVALID_POINTER);
    7461
    7562    /* General stuff. */
     63    pThread->pAnchor    = NULL;
    7664    pThread->Node.pPrev = NULL;
    7765    pThread->Node.pNext = NULL;
     
    9280    pThread->uPID         = 0;          /* Don't have a PID yet. */
    9381    pThread->pRequest     = NULL;       /* No request assigned yet. */
    94     pThread->uFlags       = uFlags;
    95     pThread->uTimeLimitMS = (   uTimeLimitMS == UINT32_MAX
    96                              || uTimeLimitMS == 0)
    97                           ? RT_INDEFINITE_WAIT : uTimeLimitMS;
     82    pThread->uFlags       = pProcess->uFlags;
     83    pThread->uTimeLimitMS = (   pProcess->uTimeLimitMS == UINT32_MAX
     84                             || pProcess->uTimeLimitMS == 0)
     85                          ? RT_INDEFINITE_WAIT : pProcess->uTimeLimitMS;
    9886
    9987    /* Prepare argument list. */
    10088    pThread->uNumArgs = 0; /* Initialize in case of RTGetOptArgvFromString() is failing ... */
    10189    rc = RTGetOptArgvFromString(&pThread->papszArgs, (int*)&pThread->uNumArgs,
    102                                 (uNumArgs > 0) ? pszArgs : "", NULL);
     90                                (pProcess->uNumArgs > 0) ? pProcess->szArgs : "", NULL);
    10391    /* Did we get the same result? */
    104     Assert(uNumArgs == pThread->uNumArgs);
     92    Assert(pProcess->uNumArgs == pThread->uNumArgs);
    10593
    10694    if (RT_SUCCESS(rc))
     
    10896        /* Prepare environment list. */
    10997        pThread->uNumEnvVars = 0;
    110         if (uNumEnvVars)
    111         {
    112             pThread->papszEnv = (char **)RTMemAlloc(uNumEnvVars * sizeof(char*));
     98        if (pProcess->uNumEnvVars)
     99        {
     100            pThread->papszEnv = (char **)RTMemAlloc(pProcess->uNumEnvVars * sizeof(char*));
    113101            AssertPtr(pThread->papszEnv);
    114             pThread->uNumEnvVars = uNumEnvVars;
    115 
    116             const char *pszCur = pszEnv;
     102            pThread->uNumEnvVars = pProcess->uNumEnvVars;
     103
     104            const char *pszCur = pProcess->szEnv;
    117105            uint32_t i = 0;
    118106            uint32_t cbLen = 0;
    119             while (cbLen < cbEnv)
     107            while (cbLen < pProcess->cbEnv)
    120108            {
    121109                /* sanity check */
    122                 if (i >= uNumEnvVars)
     110                if (i >= pProcess->uNumEnvVars)
    123111                {
    124112                    rc = VERR_INVALID_PARAMETER;
     
    138126
    139127        /* The actual command to execute. */
    140         pThread->pszCmd      = RTStrDup(pszCmd);
     128        pThread->pszCmd      = RTStrDup(pProcess->szCmd);
    141129        AssertPtr(pThread->pszCmd);
    142130
    143131        /* User management. */
    144         pThread->pszUser     = RTStrDup(pszUser);
     132        pThread->pszUser     = RTStrDup(pProcess->szUser);
    145133        AssertPtr(pThread->pszUser);
    146         pThread->pszPassword = RTStrDup(pszPassword);
     134        pThread->pszPassword = RTStrDup(pProcess->szPassword);
    147135        AssertPtr(pThread->pszPassword);
    148136    }
    149137
    150138    if (RT_FAILURE(rc)) /* Clean up on failure. */
    151         vboxServiceControlThreadFree(pThread);
     139        VBoxServiceControlThreadFree(pThread);
    152140    return rc;
    153141}
     
    160148 * @param   pThread                 Thread to shut down.
    161149 */
    162 static int vboxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pThread)
     150int VBoxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pThread)
    163151{
    164152    AssertPtrReturn(pThread, VERR_INVALID_POINTER);
    165153
    166     VBoxServiceVerbose(3, "ControlThread: [PID %u]: Freeing thread data ...\n",
     154    VBoxServiceVerbose(3, "ControlThread: [PID %u]: Freeing ...\n",
    167155                       pThread->uPID);
    168156
    169     int rc = vboxServiceControlThreadRequestCancel(pThread->pRequest);
    170     if (RT_FAILURE(rc))
    171         VBoxServiceError("ControlThread: [PID %u]: Signalling request event failed, rc=%Rrc\n",
    172                      pThread->uPID, rc);
    173 
    174     rc = RTCritSectEnter(&pThread->CritSect);
     157    int rc = RTCritSectEnter(&pThread->CritSect);
    175158    if (RT_SUCCESS(rc))
    176159    {
     
    189172        VBoxServiceVerbose(3, "ControlThread: [PID %u]: Setting stopped state\n",
    190173                           pThread->uPID);
    191 
    192         /* Set stopped status. */
    193         ASMAtomicXchgBool(&pThread->fStopped, true);
    194174
    195175        rc = RTCritSectLeave(&pThread->CritSect);
     
    220200 * @param   pThread             Thread to shut down.
    221201 */
    222 int VBoxServiceControlThreadSignalShutdown(const PVBOXSERVICECTRLTHREAD pThread)
     202int VBoxServiceControlThreadStop(const PVBOXSERVICECTRLTHREAD pThread)
    223203{
    224204    AssertPtrReturn(pThread, VERR_INVALID_POINTER);
    225205
    226     VBoxServiceVerbose(3, "ControlThread: [PID %u]: Signalling shutdown ...\n",
     206    VBoxServiceVerbose(3, "ControlThread: [PID %u]: Stopping ...\n",
    227207                       pThread->uPID);
     208
     209    int rc = vboxServiceControlThreadRequestCancel(pThread->pRequest);
     210    if (RT_FAILURE(rc))
     211        VBoxServiceError("ControlThread: [PID %u]: Signalling request event failed, rc=%Rrc\n",
     212                         pThread->uPID, rc);
    228213
    229214    /* Do *not* set pThread->fShutdown or other stuff here!
     
    231216
    232217    PVBOXSERVICECTRLREQUEST pRequest;
    233     int rc = VBoxServiceControlThreadRequestAlloc(&pRequest, VBOXSERVICECTRLREQUEST_QUIT);
     218    rc = VBoxServiceControlThreadRequestAlloc(&pRequest, VBOXSERVICECTRLREQUEST_QUIT);
    234219    if (RT_SUCCESS(rc))
    235220    {
     
    252237 * @param   RTMSINTERVAL        Timeout in ms to wait for shutdown.
    253238 */
    254 int VBoxServiceControlThreadWaitForShutdown(const PVBOXSERVICECTRLTHREAD pThread,
    255                                             RTMSINTERVAL msTimeout)
     239int VBoxServiceControlThreadWait(const PVBOXSERVICECTRLTHREAD pThread,
     240                                 RTMSINTERVAL msTimeout)
    256241{
    257242    AssertPtrReturn(pThread, VERR_INVALID_POINTER);
    258243    int rc = VINF_SUCCESS;
    259244    if (   pThread->Thread != NIL_RTTHREAD
    260         && !ASMAtomicReadBool(&pThread->fStopped)) /* Only shutdown threads which aren't yet. */
     245        && ASMAtomicReadBool(&pThread->fStarted))
    261246    {
    262247        VBoxServiceVerbose(2, "ControlThread: [PID %u]: Waiting for shutdown ...\n",
     
    286271
    287272/**
    288  * Returns whether a guest process thread still is up and running.
    289  *
    290  * @return  true if thread is running, false if not.
    291  * @param   pThread             Thread to determine current status for.
    292  */
    293 bool VBoxServiceControlThreadActive(const PVBOXSERVICECTRLTHREAD pThread)
    294 {
    295     AssertPtrReturn(pThread, false);
    296 
    297     int rc = RTCritSectEnter(&pThread->CritSect);
    298     if (RT_SUCCESS(rc))
    299     {
    300         /* We only are interested whether the thread really is alive
    301          * and kicking or not, meaning:
    302          * - thread was started
    303          * - thread is able to serve IPC messages
    304          *
    305          * Even if the fShutdown flag is set this means the thread should be
    306          * considered as being running (destruction phase).
    307          */
    308         bool fRunning = !pThread->fStopped;
    309 
    310         rc = RTCritSectLeave(&pThread->CritSect);
    311         AssertRC(rc);
    312 
    313         return fRunning;
    314     }
    315 
    316     return false;
    317 }
    318 
    319 
    320 /**
    321273 * Closes the stdin pipe of a guest process.
    322274 *
     
    509461        case VBOXSERVICECTRLREQUEST_STDIN_WRITE_EOF:
    510462        {
    511             AssertPtrReturn(pRequest->pvData, VERR_INVALID_POINTER);
    512             AssertReturn(pRequest->cbData, VERR_INVALID_PARAMETER);
    513 
    514463            size_t cbWritten = 0;
    515             if (   *phStdInW != NIL_RTPIPE
    516                 && pRequest->cbData)
     464            if (pRequest->cbData)
    517465            {
    518                 rcReq = RTPipeWrite(*phStdInW,
    519                                     pRequest->pvData, pRequest->cbData, &cbWritten);
     466                AssertPtrReturn(pRequest->pvData, VERR_INVALID_POINTER);
     467                if (*phStdInW != NIL_RTPIPE)
     468                {
     469                    rcReq = RTPipeWrite(*phStdInW,
     470                                        pRequest->pvData, pRequest->cbData, &cbWritten);
     471                }
     472                else
     473                    rcReq = VINF_EOF;
    520474            }
    521             else
    522                 rcReq = VINF_EOF;
    523475
    524476            /*
     
    1018970        return VINF_SUCCESS;
    1019971
    1020     VBoxServiceVerbose(4, "ControlThread: Cancelling request 0x%p\n", pReq);
     972    VBoxServiceVerbose(4, "ControlThread: Cancelling request=0x%p\n", pReq);
    1021973
    1022974    return RTSemEventMultiSignal(pReq->Event);
     
    1034986    AssertPtrReturnVoid(pReq);
    1035987
    1036     VBoxServiceVerbose(4, "ControlThread: Freeing request 0x%p (event 0x%p)\n",
     988    VBoxServiceVerbose(4, "ControlThread: Freeing request=0x%p (event=%RTsem)\n",
    1037989                       pReq, &pReq->Event);
    1038990
     
    14011353    VBoxServiceVerbose(3, "ControlThread: Thread of process \"%s\" started\n", pThread->pszCmd);
    14021354
    1403     int rc = VbglR3GuestCtrlConnect(&pThread->uClientID);
     1355    int rc = VBoxServiceControlListSet(VBOXSERVICECTRLTHREADLIST_RUNNING, pThread);
     1356    AssertRC(rc);
     1357
     1358    rc = VbglR3GuestCtrlConnect(&pThread->uClientID);
    14041359    if (RT_FAILURE(rc))
    14051360    {
     
    15211476                                                                          hProcess, pThread->uTimeLimitMS, hPollSet,
    15221477                                                                          &pThread->pipeStdInW, &pipeStdOutR, &pipeStdErrR);
     1478
    15231479                                    /*
    15241480                                     * The handles that are no longer in the set have
     
    15671523    }
    15681524
     1525    /* Move thread to stopped thread list. */
     1526    int rc2 = VBoxServiceControlListSet(VBOXSERVICECTRLTHREADLIST_STOPPED, pThread);
     1527    AssertRC(rc2);
     1528
    15691529    if (pThread->uClientID)
    15701530    {
    1571         int rc2;
    15721531        if (RT_FAILURE(rc))
    15731532        {
     
    16011560                       pThread->uPID, pThread->pszCmd, rc);
    16021561
     1562    /* Update started/stopped status. */
     1563    ASMAtomicXchgBool(&pThread->fStopped, true);
    16031564    ASMAtomicXchgBool(&pThread->fStarted, false);
    16041565
     
    16101571        RTThreadUserSignal(RTThreadSelf());
    16111572
    1612     /*
    1613      * Remove thread from global thread list. After this it's safe to shutdown
    1614      * and deallocate this thread.
    1615      */
    1616     VBoxServiceControlRemoveThread(pThread);
    1617 
    1618     int rc2 = vboxServiceControlThreadFree(pThread);
    1619     if (RT_SUCCESS(rc))
    1620         rc = rc2;
    1621 
    16221573    return rc;
    16231574}
     
    16451596 *
    16461597 * @return  IPRT status code.
    1647  * @param   uClientID                   Client ID for accessing host service.
    16481598 * @param   uContextID                  Context ID to associate the process to start with.
    1649  * @param   pszCmd                      Full qualified path of process to start (without arguments).
    1650  * @param   uFlags                      Process execution flags.
    1651  * @param   pszArgs                     String of arguments to pass to the process to start.
    1652  * @param   uNumArgs                    Number of arguments specified in pszArgs.
    1653  * @param   pszEnv                      String of environment variables ("FOO=BAR") to pass to the process
    1654  *                                      to start.
    1655  * @param   cbEnv                       Size (in bytes) of environment variables.
    1656  * @param   uNumEnvVars                 Number of environment variables specified in pszEnv.
    1657  * @param   pszUser                     User name (account) to start the process under.
    1658  * @param   pszPassword                 Password of specified user name (account).
    1659  * @param   uTimeLimitMS                Time limit (in ms) of the process' life time.
    1660  * @param   ppNode                      The thread's list node to insert into the global thread list
    1661  *                                      on success.
    1662  *
    1663  ** @todo Put (all?) these parameters into a struct!
    1664  */
    1665 int VBoxServiceControlThreadStart(uint32_t uClientID, uint32_t uContextID,
    1666                                   const char *pszCmd, uint32_t uFlags,
    1667                                   const char *pszArgs, uint32_t uNumArgs,
    1668                                   const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
    1669                                   const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS,
    1670                                   PRTLISTNODE *ppNode)
    1671 {
    1672     AssertPtrReturn(ppNode, VERR_INVALID_POINTER);
     1599 * @param   pProcess                    Process info.
     1600 */
     1601int VBoxServiceControlThreadStart(uint32_t uContextID,
     1602                                  PVBOXSERVICECTRLPROCESS pProcess)
     1603{
     1604    AssertPtrReturn(pProcess, VERR_INVALID_POINTER);
    16731605
    16741606    /*
     
    16791611        return VERR_NO_MEMORY;
    16801612
    1681     int rc = gstsvcCntlExecThreadInit(pThread,
    1682                                       uContextID,
    1683                                       pszCmd, uFlags,
    1684                                       pszArgs, uNumArgs,
    1685                                       pszEnv, cbEnv, uNumEnvVars,
    1686                                       pszUser, pszPassword,
    1687                                       uTimeLimitMS);
     1613    int rc = gstsvcCntlExecThreadInit(pThread, pProcess, uContextID);
    16881614    if (RT_SUCCESS(rc))
    16891615    {
     
    16931619        rc = RTThreadCreateF(&pThread->Thread, VBoxServiceControlThread,
    16941620                             pThread /*pvUser*/, 0 /*cbStack*/,
    1695                              RTTHREADTYPE_DEFAULT, 0 /* Flags */, "gctl%u", s_uCtrlExecThread);
     1621                             RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "gctl%u", s_uCtrlExecThread);
    16961622        if (RT_FAILURE(rc))
    16971623        {
     
    17041630
    17051631            /* Wait for the thread to initialize. */
    1706             RTThreadUserWait(pThread->Thread, 60 * 1000 /* 60 seconds max. */);
    1707             if (ASMAtomicReadBool(&pThread->fShutdown))
     1632            rc = RTThreadUserWait(pThread->Thread, 60 * 1000 /* 60 seconds max. */);
     1633            AssertRC(rc);
     1634            if (   ASMAtomicReadBool(&pThread->fShutdown)
     1635                || RT_FAILURE(rc))
    17081636            {
    1709                 VBoxServiceError("ControlThread: Thread for process \"%s\" failed to start!\n", pszCmd);
    1710                 rc = VERR_GENERAL_FAILURE;
     1637                VBoxServiceError("ControlThread: Thread for process \"%s\" failed to start, rc=%Rrc\n",
     1638                                 pProcess->szCmd, rc);
    17111639            }
    17121640            else
    17131641            {
    1714                 pThread->fStarted = true;
    1715 
    1716                 /* Return the thread's node. */
    1717                 *ppNode = &pThread->Node;
     1642                ASMAtomicXchgBool(&pThread->fStarted, true);
    17181643            }
    17191644        }
     
    17421667
    17431668    int rc = VINF_SUCCESS;
    1744     PVBOXSERVICECTRLTHREAD pThread = VBoxServiceControlGetThreadLocked(uPID);
     1669    PVBOXSERVICECTRLTHREAD pThread = VBoxServiceControlLockThread(uPID);
    17451670    if (pThread)
    17461671    {
     
    17731698        }
    17741699
    1775         VBoxServiceControlThreadUnlock(pThread);
     1700        VBoxServiceControlUnlockThread(pThread);
    17761701    }
    17771702    else /* PID not found! */
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r39843 r39906  
    2929
    3030#include <VBox/VBoxGuestLib.h>
     31#include <VBox/HostServices/GuestControlSvc.h>
    3132
    3233/**
     
    156157
    157158/**
     159 * Thread list types.
     160 */
     161typedef enum VBOXSERVICECTRLTHREADLISTTYPE
     162{
     163    /** Unknown list -- uncool to use. */
     164    VBOXSERVICECTRLTHREADLIST_UNKNOWN       = 0,
     165    /** Stopped list: Here all guest threads end up
     166     *  when they reached the stopped state and can
     167     *  be shut down / free'd safely. */
     168    VBOXSERVICECTRLTHREADLIST_STOPPED       = 1,
     169    /**
     170     * Started list: Here all threads are registered
     171     * when they're up and running (that is, accepting
     172     * commands).
     173     */
     174    VBOXSERVICECTRLTHREADLIST_RUNNING       = 2
     175} VBOXSERVICECTRLTHREADLISTTYPE;
     176
     177/**
    158178 * Structure to perform a request on a started guest
    159179 * process. Needed for letting the main guest control thread
     
    183203
    184204/**
     205 * Structure holding information for starting a guest
     206 * process.
     207 */
     208typedef struct VBOXSERVICECTRLPROCESS
     209{
     210    /** Full qualified path of process to start (without arguments). */
     211    char szCmd[GUESTPROCESS_MAX_CMD_LEN];
     212    /** Process execution flags. @sa */
     213    uint32_t uFlags;
     214    /** Command line arguments. */
     215    char szArgs[GUESTPROCESS_MAX_ARGS_LEN];
     216    /** Number of arguments specified in pszArgs. */
     217    uint32_t uNumArgs;
     218    /** String of environment variables ("FOO=BAR") to pass to the process
     219      * to start. */
     220    char szEnv[GUESTPROCESS_MAX_ENV_LEN];
     221    /** Size (in bytes) of environment variables block. */
     222    uint32_t cbEnv;
     223    /** Number of environment variables specified in pszEnv. */
     224    uint32_t uNumEnvVars;
     225    /** User name (account) to start the process under. */
     226    char szUser[GUESTPROCESS_MAX_USER_LEN];
     227    /** Password of specified user name (account). */
     228    char szPassword[GUESTPROCESS_MAX_PASSWORD_LEN];
     229    /** Time limit (in ms) of the process' life time. */
     230    uint32_t uTimeLimitMS;
     231} VBOXSERVICECTRLPROCESS;
     232/** Pointer to a guest process block. */
     233typedef VBOXSERVICECTRLPROCESS *PVBOXSERVICECTRLPROCESS;
     234
     235/**
    185236 * Structure for holding data for one (started) guest process.
    186237 */
    187238typedef struct VBOXSERVICECTRLTHREAD
    188239{
     240    /** Pointer to list archor of following
     241     *  list node.
     242     *  @todo Would be nice to have a RTListGetAnchor(). */
     243    PRTLISTANCHOR                   pAnchor;
    189244    /** Node. */
    190245    RTLISTNODE                      Node;
     
    330385
    331386#ifdef VBOX_WITH_GUEST_CONTROL
    332 /* Guest control functions. */
    333 extern PVBOXSERVICECTRLTHREAD VBoxServiceControlGetThreadLocked(uint32_t uPID);
    334 extern void         VBoxServiceControlThreadUnlock(const PVBOXSERVICECTRLTHREAD pThread);
    335 extern int          VBoxServiceControlAssignPID(PVBOXSERVICECTRLTHREAD pThread, uint32_t uPID);
    336 extern void         VBoxServiceControlRemoveThread(const PVBOXSERVICECTRLTHREAD pThread);
    337 /* Guest process functions. */
    338 extern bool         VBoxServiceControlThreadActive(const PVBOXSERVICECTRLTHREAD pThread);
    339 extern int          VBoxServiceControlThreadStart(uint32_t uClientID, uint32_t uContext,
    340                                                   const char *pszCmd, uint32_t uFlags,
    341                                                   const char *pszArgs, uint32_t uNumArgs,
    342                                                   const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
    343                                                   const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS,
    344                                                   PRTLISTNODE *ppNode);
    345 extern int          VBoxServiceControlThreadRequestAlloc(PVBOXSERVICECTRLREQUEST   *ppReq,
    346                                                          VBOXSERVICECTRLREQUESTTYPE enmType);
    347 extern int          VBoxServiceControlThreadRequestAllocEx(PVBOXSERVICECTRLREQUEST    *ppReq,
    348                                                            VBOXSERVICECTRLREQUESTTYPE  enmType,
    349                                                            void*                       pbData,
    350                                                            size_t                      cbData,
    351                                                            uint32_t                    uCID);
    352 extern void         VBoxServiceControlThreadRequestFree(PVBOXSERVICECTRLREQUEST pReq);
    353 extern int          VBoxServiceControlThreadPerform(uint32_t uPID, PVBOXSERVICECTRLREQUEST pRequest);
    354 extern int          VBoxServiceControlThreadSignalShutdown(const PVBOXSERVICECTRLTHREAD pThread);
    355 extern int          VBoxServiceControlThreadWaitForShutdown(const PVBOXSERVICECTRLTHREAD pThread, RTMSINTERVAL msTimeout);
     387/* Guest control main thread functions. */
     388extern int                      VBoxServiceControlAssignPID(PVBOXSERVICECTRLTHREAD pThread, uint32_t uPID);
     389extern int                      VBoxServiceControlListSet(VBOXSERVICECTRLTHREADLISTTYPE enmList,
     390                                                          PVBOXSERVICECTRLTHREAD pThread);
     391extern PVBOXSERVICECTRLTHREAD   VBoxServiceControlLockThread(uint32_t uPID);
     392extern void                     VBoxServiceControlUnlockThread(const PVBOXSERVICECTRLTHREAD pThread);
     393extern int                      VBoxServiceControlSetInactive(PVBOXSERVICECTRLTHREAD pThread);
     394/* Per-thread guest process functions. */
     395extern int                      VBoxServiceControlThreadStart(uint32_t uContext,
     396                                                              PVBOXSERVICECTRLPROCESS pProcess);
     397extern int                      VBoxServiceControlThreadPerform(uint32_t uPID, PVBOXSERVICECTRLREQUEST pRequest);
     398extern int                      VBoxServiceControlThreadStop(const PVBOXSERVICECTRLTHREAD pThread);
     399extern int                      VBoxServiceControlThreadWait(const PVBOXSERVICECTRLTHREAD pThread, RTMSINTERVAL msTimeout);
     400extern int                      VBoxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pThread);
     401/* Request handling. */
     402extern int                      VBoxServiceControlThreadRequestAlloc(PVBOXSERVICECTRLREQUEST   *ppReq,
     403                                                                     VBOXSERVICECTRLREQUESTTYPE enmType);
     404extern int                      VBoxServiceControlThreadRequestAllocEx(PVBOXSERVICECTRLREQUEST    *ppReq,
     405                                                                       VBOXSERVICECTRLREQUESTTYPE  enmType,
     406                                                                       void*                       pbData,
     407                                                                       size_t                      cbData,
     408                                                                       uint32_t                    uCID);
     409extern void                     VBoxServiceControlThreadRequestFree(PVBOXSERVICECTRLREQUEST pReq);
    356410#endif /* VBOX_WITH_GUEST_CONTROL */
    357411
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