VirtualBox

Changeset 28119 in vbox for trunk/src/VBox/Additions/common


Ignore:
Timestamp:
Apr 9, 2010 7:54:19 AM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
59837
Message:

Guest Control/VBoxService: Threading.

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

Legend:

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

    r28086 r28119  
    9696static int VBoxServiceControlHandleCmdExec(uint32_t u32ClientId, uint32_t uNumParms)
    9797{
    98     VBOXSERVICECTRLPROCDATA execData;
    99     execData.cbEnv = sizeof(execData.szEnv);
     98    char szCmd[_1K];
     99    uint32_t uFlags;
     100    char szArgs[_1K];
     101    uint32_t uNumArgs;
     102    char szEnv[_64K];
     103    uint32_t cbEnv = sizeof(szEnv);
     104    uint32_t uNumEnvVars;
     105    char szStdIn[_1K];
     106    char szStdOut[_1K];
     107    char szStdErr[_1K];
     108    char szUser[128];
     109    char szPassword[128];
     110    uint32_t uTimeLimitMS;
    100111
    101112    int rc = VbglR3GuestCtrlGetHostCmdExec(u32ClientId, uNumParms,
    102                                            execData.szCmd, sizeof(execData.szCmd),
    103                                            &execData.uFlags,
    104                                            execData.szArgs, sizeof(execData.szArgs), &execData.uNumArgs,
    105                                            execData.szEnv, &execData.cbEnv, &execData.uNumEnvVars,
    106                                            execData.szStdIn, sizeof(execData.szStdIn),
    107                                            execData.szStdOut, sizeof(execData.szStdOut),
    108                                            execData.szStdErr, sizeof(execData.szStdErr),
    109                                            execData.szUser, sizeof(execData.szUser),
    110                                            execData.szPassword, sizeof(execData.szPassword),
    111                                            &execData.uTimeLimitMS);
     113                                           /* Command */
     114                                           szCmd,      sizeof(szCmd),
     115                                           /* Flags */
     116                                           &uFlags,
     117                                           /* Arguments */
     118                                           szArgs,     sizeof(szArgs), &uNumArgs,
     119                                           /* Environment */
     120                                           szEnv, &cbEnv, &uNumEnvVars,
     121                                           /* Pipes */
     122                                           szStdIn,    sizeof(szStdIn),
     123                                           szStdOut,   sizeof(szStdOut),
     124                                           szStdErr,   sizeof(szStdErr),
     125                                           /* Credentials */
     126                                           szUser,     sizeof(szUser),
     127                                           szPassword, sizeof(szPassword),
     128                                           /* Timelimit */
     129                                           &uTimeLimitMS);
    112130    if (RT_FAILURE(rc))
    113131    {
     
    115133    }
    116134    else
    117     {
    118         /* Adjust time limit value. */
    119         execData.uTimeLimitMS = UINT32_MAX ?
    120             RT_INDEFINITE_WAIT : execData.uTimeLimitMS;
    121 
    122         /* Prepare argument list. */
    123         char **ppaArg;
    124         int iArgs;
    125         rc = RTGetOptArgvFromString(&ppaArg, &iArgs,
    126                                     execData.uNumArgs ? execData.szArgs : "", NULL);
    127         Assert(execData.uNumArgs == iArgs);
    128         if (RT_SUCCESS(rc))
    129         {
    130             /* Prepare environment list. */
    131             char **ppaEnv;
    132             if (execData.uNumEnvVars)
    133             {
    134                 ppaEnv = (char**)RTMemAlloc(execData.uNumEnvVars * sizeof(char*));
    135                 AssertPtr(ppaEnv);
    136 
    137                 char *pcCur = execData.szEnv;
    138                 uint32_t i = 0;
    139                 uint32_t cbLen = 0;
    140                 while (cbLen < execData.cbEnv)
    141                 {
    142                     if (RTStrAPrintf(&ppaEnv[i++], "%s", pcCur) < 0)
    143                     {
    144                         rc = VERR_NO_MEMORY;
    145                         break;
    146                     }
    147                     cbLen += strlen(pcCur) + 1; /* Skip terminating zero. */
    148                     pcCur += cbLen;
    149                 }
    150             }
    151 
    152             if (RT_SUCCESS(rc))
    153             {
    154                 /* Do the actual execution. */
    155                 rc = VBoxServiceControlExecProcess(&execData, ppaArg, ppaEnv);
    156                 if (RT_FAILURE(rc))
    157                     VBoxServiceVerbose(3, "Control: Could not execute process \"%s\"! Error: %Rrc\n",
    158                                        execData.szCmd, rc);
    159                 /* Cleanup. */
    160                 if (execData.uNumEnvVars)
    161                 {
    162                     for (uint32_t i = 0; i < execData.uNumEnvVars; i++)
    163                         RTStrFree(ppaEnv[i]);
    164                     RTMemFree(ppaEnv);
    165                 }
    166             }
    167             RTGetOptArgvFree(ppaArg);
    168         }
     135    {     
     136        rc = VBoxServiceControlExecProcess(szCmd, uFlags, szArgs, uNumArgs,                                           
     137                                           szEnv, cbEnv, uNumEnvVars,
     138                                           szStdIn, szStdOut, szStdErr,
     139                                           szUser, szPassword, uTimeLimitMS);
    169140    }
    170141    return rc;
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp

    r28029 r28119  
    499499}
    500500
    501 int VBoxServiceControlExecProcess(PVBOXSERVICECTRLPROCDATA pExecData,
    502                                   const char * const      *papszArgs,
    503                                   const char * const      *papszEnv)
    504 {
    505     AssertPtr(pExecData);
     501/** Allocates and gives back a thread data struct which then can be used by the worker thread. */
     502PVBOXSERVICECTRLTHREADDATA VBoxServiceControlExecAllocateThreadData(const char *pszCmd, uint32_t uFlags,
     503                                                                    const char *pszArgs, uint32_t uNumArgs,                                           
     504                                                                    const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
     505                                                                    const char *pszStdIn, const char *pszStdOut, const char *pszStdErr,
     506                                                                    const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS)
     507{
     508    PVBOXSERVICECTRLTHREADDATA pData = (PVBOXSERVICECTRLTHREADDATA)RTMemAlloc(sizeof(VBOXSERVICECTRLTHREADDATA));
     509    if (pData == NULL)
     510        return NULL;
     511
     512    pData->pszCmd = RTStrDup(pszCmd);
     513    pData->uFlags = uFlags;
     514
     515    /* Prepare argument list. */
     516    int rc = RTGetOptArgvFromString(&pData->papszArgs, (int*)&pData->uNumArgs,
     517                                    pszArgs ? pszArgs : "", NULL);
     518    Assert(uNumArgs == pData->uNumArgs);
     519    if (RT_SUCCESS(rc))
     520    {
     521        /* Prepare environment list. */
     522        if (uNumEnvVars)
     523        {
     524            pData->papszEnv = (char**)RTMemAlloc(uNumEnvVars * sizeof(char*));
     525            AssertPtr(pData->papszEnv);
     526            pData->uNumEnvVars = uNumEnvVars;
     527
     528            const char *pcCur = pszEnv;
     529            uint32_t i = 0;
     530            uint32_t cbLen = 0;
     531            while (cbLen < cbEnv)
     532            {
     533                if (RTStrAPrintf(& pData->papszEnv[i++], "%s", pcCur) < 0)
     534                {
     535                    rc = VERR_NO_MEMORY;
     536                    break;
     537                }
     538                cbLen += strlen(pcCur) + 1; /* Skip terminating zero. */
     539                pcCur += cbLen;
     540            }
     541        }
     542
     543        pData->pszStdIn = RTStrDup(pszStdIn);
     544        pData->pszStdOut = RTStrDup(pszStdOut);
     545        pData->pszStdErr = RTStrDup(pszStdErr);
     546        pData->pszUser = RTStrDup(pszUser);
     547        pData->pszPassword = RTStrDup(pszPassword);
     548        pData->uTimeLimitMS = uTimeLimitMS;
     549    }
     550
     551    /* Adjust time limit value. */
     552    pData->uTimeLimitMS = (   (uTimeLimitMS == UINT32_MAX)
     553                           || (uTimeLimitMS == 0)) ?
     554                           RT_INDEFINITE_WAIT : uTimeLimitMS;
     555    return pData;
     556}
     557
     558/** Frees an allocated thread data structure along with all its allocated parameters. */
     559void VBoxServiceControlExecFreeThreadData(PVBOXSERVICECTRLTHREADDATA pData)
     560{
     561    AssertPtr(pData);
     562    RTStrFree(pData->pszCmd);
     563    if (pData->uNumEnvVars)
     564    {
     565        for (uint32_t i = 0; i < pData->uNumEnvVars; i++)
     566            RTStrFree(pData->papszEnv[i]);
     567        RTMemFree(pData->papszEnv);
     568    }
     569    RTGetOptArgvFree(pData->papszArgs);
     570    RTStrFree(pData->pszStdIn);
     571    RTStrFree(pData->pszStdOut);
     572    RTStrFree(pData->pszStdErr);
     573    RTStrFree(pData->pszUser);
     574    RTStrFree(pData->pszPassword);
     575
     576    RTMemFree(pData);
     577}
     578
     579DECLCALLBACK(int) VBoxServiceControlExecProcessWorker(PVBOXSERVICECTRLTHREADDATA pData)
     580{
     581    AssertPtr(pData);
     582    AssertPtr(pData->papszArgs);
     583    AssertPtr(pData->papszEnv);
     584
     585    /*
     586     * Tell the control thread that it can continue
     587     * spawning services.
     588     */
     589    RTThreadUserSignal(RTThreadSelf());
     590    VBoxServiceVerbose(3, "Control: Thread of process \"%s\" started.", pData->pszCmd);
    506591
    507592    /*
     
    513598    {
    514599        size_t i;
    515         for (i = 0; i < pExecData->uNumEnvVars; i++)
    516         {
    517             rc = RTEnvPutEx(hEnv, papszEnv[i]);
     600        for (i = 0; i < pData->uNumEnvVars; i++)
     601        {
     602            rc = RTEnvPutEx(hEnv, pData->papszEnv[i]);
    518603            if (RT_FAILURE(rc))
    519604                break;
     
    559644                            {
    560645                                RTPROCESS hProcess;
    561                                 rc = RTProcCreateEx(pExecData->szCmd, papszArgs, hEnv, 0 /*fFlags*/,
     646                                rc = RTProcCreateEx(pData->pszCmd, pData->papszArgs, hEnv, pData->uFlags,
    562647                                                    phStdIn, phStdOut, phStdErr,
    563648                                                    /*pszUsername, pszPassword,*/ NULL, NULL,
     
    565650                                if (RT_SUCCESS(rc))
    566651                                {
     652                                    VBoxServiceVerbose(3, "Control: Process \"%s\" started.\n", pData->pszCmd);
     653                                    /** @todo Dump a bit more info here. */
     654
    567655                                    /*
    568656                                     * Close the child ends of any pipes and redirected files.
     
    575663                                    phStdErr   = NULL;
    576664
    577                                     rc = VBoxServiceControlExecProcLoop(hProcess, pExecData->uTimeLimitMS, hPollSet,
     665                                    rc = VBoxServiceControlExecProcLoop(hProcess, pData->uTimeLimitMS, hPollSet,
    578666                                                                        hStdInW, hStdOutR, hStdErrR);
    579667                                    /*
     
    604692        RTEnvDestroy(hEnv);
    605693    }
     694
     695    VBoxServiceVerbose(3, "Control: Thread of process \"%s\" ended with rc=%Rrc.\n", pData->pszCmd, rc);
     696
     697    /*
     698     * Since we (hopefully) are the one ones that hold the thread data,
     699     * destroy them now.
     700     */
     701    VBoxServiceControlExecFreeThreadData(pData);
    606702    return rc;
    607703}
    608704
     705static DECLCALLBACK(int) VBoxServiceControlExecThread(RTTHREAD ThreadSelf, void *pvUser)
     706{
     707    PVBOXSERVICECTRLTHREADDATA pData = (PVBOXSERVICECTRLTHREADDATA)pvUser;
     708    return VBoxServiceControlExecProcessWorker(pData);
     709}
     710
     711int VBoxServiceControlExecProcess(const char *pszCmd, uint32_t uFlags,
     712                                  const char *pszArgs, uint32_t uNumArgs,                                           
     713                                  const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
     714                                  const char *pszStdIn, const char *pszStdOut, const char *pszStdErr,
     715                                  const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS)
     716{
     717    PVBOXSERVICECTRLTHREADDATA pThreadData =
     718        VBoxServiceControlExecAllocateThreadData(pszCmd, uFlags,
     719                                                 pszArgs, uNumArgs,
     720                                                 pszEnv, cbEnv, uNumEnvVars,
     721                                                 pszStdIn, pszStdOut, pszStdErr,
     722                                                 pszUser, pszPassword,
     723                                                 uTimeLimitMS);
     724    int rc = VINF_SUCCESS;
     725    if (pThreadData)
     726    {   
     727        rc = RTThreadCreate(NULL, VBoxServiceControlExecThread,
     728                                (void *)(PVBOXSERVICECTRLTHREADDATA)pThreadData, 0,
     729                                RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Exec");
     730        if (RT_FAILURE(rc))
     731        {
     732            VBoxServiceError("Control: RTThreadCreate failed, rc=%Rrc\n, threadData=%p",
     733                             rc, pThreadData);
     734            VBoxServiceControlExecFreeThreadData(pThreadData);
     735        }
     736    }
     737    else
     738        rc = VERR_NO_MEMORY;
     739    return rc;
     740}
     741
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r27972 r28119  
    126126
    127127#ifdef VBOX_WITH_GUEST_CONTROL
    128 /* Structure for holding process execution data. */
    129 typedef struct _VBoxServiceControlProcessData
    130 {
    131     char szCmd[_1K];
    132     uint32_t uFlags;
    133     char szArgs[_1K];
    134     uint32_t uNumArgs;
    135     char szEnv[_64K];
    136     uint32_t cbEnv;
    137     uint32_t uNumEnvVars;
    138     char szStdIn[_1K];
    139     char szStdOut[_1K];
    140     char szStdErr[_1K];
    141     char szUser[128];
    142     char szPassword[128];
    143     uint32_t uTimeLimitMS;
    144 } VBOXSERVICECTRLPROCDATA;
    145 /** Pointer to execution data. */
    146 typedef VBOXSERVICECTRLPROCDATA *PVBOXSERVICECTRLPROCDATA;
     128/* Structure for holding thread relevant data. */
     129typedef struct
     130{
     131    char     *pszCmd;
     132    uint32_t  uFlags;
     133    char    **papszArgs;
     134    uint32_t  uNumArgs;
     135    char    **papszEnv;
     136    uint32_t  uNumEnvVars;
     137    char     *pszStdIn;
     138    char     *pszStdOut;
     139    char     *pszStdErr;
     140    char     *pszUser;
     141    char     *pszPassword;
     142    uint32_t  uTimeLimitMS;
     143} VBOXSERVICECTRLTHREADDATA;
     144/** Pointer to thread data. */
     145typedef VBOXSERVICECTRLTHREADDATA *PVBOXSERVICECTRLTHREADDATA;
     146
    147147/**
    148148 * For buffering process input supplied by the client.
    149149 */
    150 typedef struct _VBoxServiceControlStdInBuf
     150typedef struct
    151151{
    152152    /** The mount of buffered data. */
     
    210210
    211211#ifdef VBOX_WITH_GUEST_CONTROL
    212 extern int  VBoxServiceControlExecProcess(PVBOXSERVICECTRLPROCDATA pExecData,
    213                                           const char * const      *papszArgs,
    214                                           const char * const      *papszEnv);
     212extern int VBoxServiceControlExecProcess(const char *pszCmd, uint32_t uFlags,
     213                                         const char *pszArgs, uint32_t uNumArgs,                                           
     214                                         const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
     215                                         const char *pszStdIn, const char *pszStdOut, const char *pszStdErr,
     216                                         const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS);
    215217#endif
    216218
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