VirtualBox

Changeset 45604 in vbox for trunk/src


Ignore:
Timestamp:
Apr 18, 2013 12:21:20 PM (12 years ago)
Author:
vboxsync
Message:

VBoxService/GuestCtrl: Added asynchronous request handling, more fixes for testcases.

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

Legend:

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

    r45415 r45604  
    5050    /** Unknown request. */
    5151    VBOXSERVICECTRLREQUEST_UNKNOWN          = 0,
    52     /** Main control thread asked used to quit. */
    53     VBOXSERVICECTRLREQUEST_QUIT             = 1,
    5452    /** Performs reading from stdout. */
    5553    VBOXSERVICECTRLREQUEST_PROC_STDOUT      = 50,
     
    9997    /** Event semaphore to serialize access. */
    10098    RTSEMEVENTMULTI            Event;
     99    /** Flag indicating if this request is asynchronous or not. */
     100    bool                       fAsync;
    101101    /** The request type to handle. */
    102102    VBOXSERVICECTRLREQUESTTYPE enmType;
     
    321321      * needs (or is asked) to shutdown. */
    322322    bool volatile                   fShutdown;
    323     /** Indicator set by the service thread exiting. */
     323    /** Whether the guest process thread already was
     324     *  stopped or not. */
    324325    bool volatile                   fStopped;
    325     /** Whether the service was started or not. */
     326    /** Whether the guest process thread was started
     327     *  or not. */
    326328    bool                            fStarted;
    327329    /** Client ID. */
     
    382384extern int                      GstCntlSessionReapProcesses(PVBOXSERVICECTRLSESSION pSession);
    383385/* Per-thread guest process functions. */
    384 extern int                      GstCntlProcessPerform(PVBOXSERVICECTRLPROCESS pProcess, PVBOXSERVICECTRLREQUEST pRequest);
     386extern int                      GstCntlProcessPerform(PVBOXSERVICECTRLPROCESS pProcess, PVBOXSERVICECTRLREQUEST pRequest, bool fAsync);
    385387extern int                      GstCntlProcessStart(const PVBOXSERVICECTRLSESSION pSession, const PVBOXSERVICECTRLPROCSTARTUPINFO pStartupInfo, uint32_t uContext);
    386388extern int                      GstCntlProcessStop(PVBOXSERVICECTRLPROCESS pProcess);
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp

    r45415 r45604  
    155155            rc = gstcntlProcessRequestCancel(pProcess->pRequest);
    156156            if (RT_FAILURE(rc))
    157                 VBoxServiceError("[PID %RU32]: Signalling request event failed, rc=%Rrc\n",
     157                VBoxServiceError("[PID %RU32]: Cancelling current request failed, rc=%Rrc\n",
    158158                                 pProcess->uPID, rc);
    159159        }
     
    163163
    164164        PVBOXSERVICECTRLREQUEST pRequest;
    165         rc = GstCntlProcessRequestAlloc(&pRequest, VBOXSERVICECTRLREQUEST_QUIT);
     165        rc = GstCntlProcessRequestAlloc(&pRequest, VBOXSERVICECTRLREQUEST_PROC_TERM);
    166166        if (RT_SUCCESS(rc))
    167167        {
    168             rc = GstCntlProcessPerform(pProcess, pRequest);
     168            rc = GstCntlProcessPerform(pProcess, pRequest,
     169                                       true /* Async */);
    169170            if (RT_FAILURE(rc))
    170                 VBoxServiceVerbose(3, "[PID %RU32]: Sending quit request failed with rc=%Rrc\n",
     171                VBoxServiceVerbose(3, "[PID %RU32]: Sending termination request failed with rc=%Rrc\n",
    171172                                   pProcess->uPID, rc);
    172 
    173             GstCntlProcessRequestFree(pRequest);
     173            /* Deletion of pRequest will be done on request completion. */
    174174        }
    175175
     
    211211    /* pRc is optional. */
    212212
    213     int rc = VINF_SUCCESS;
    214     if (   pProcess->Thread != NIL_RTTHREAD
    215         && ASMAtomicReadBool(&pProcess->fStarted))
    216     {
    217         VBoxServiceVerbose(2, "[PID %RU32]: Waiting for shutdown (%RU32ms) ...\n",
    218                            pProcess->uPID, msTimeout);
    219 
    220         /* Wait a bit ... */
    221         int rcThread;
    222         rc = RTThreadWait(pProcess->Thread, msTimeout, &rcThread);
    223         if (RT_FAILURE(rc))
    224         {
    225             VBoxServiceError("[PID %RU32]: Waiting for shutting down thread returned error rc=%Rrc\n",
    226                              pProcess->uPID, rc);
    227         }
    228         else
    229         {
    230             VBoxServiceVerbose(3, "[PID %RU32]: Thread reported exit code=%Rrc\n",
    231                                pProcess->uPID, rcThread);
    232             if (pRc)
    233                 *pRc = rcThread;
    234         }
     213    AssertMsgReturn(ASMAtomicReadBool(&pProcess->fStarted),
     214                    ("Tried to wait on guest process=%p which has not been started yet\n",
     215                     pProcess), VERR_INVALID_PARAMETER);
     216
     217    /* Guest process already has been stopped, no need to wait. */
     218    if (ASMAtomicReadBool(&pProcess->fStopped))
     219        return VINF_SUCCESS;
     220
     221    VBoxServiceVerbose(2, "[PID %RU32]: Waiting for shutdown (%RU32ms) ...\n",
     222                       pProcess->uPID, msTimeout);
     223
     224    /* Wait a bit ... */
     225    int rcThread;
     226    Assert(pProcess->Thread != NIL_RTTHREAD);
     227    int rc = RTThreadWait(pProcess->Thread, msTimeout, &rcThread);
     228    if (RT_FAILURE(rc))
     229    {
     230        VBoxServiceError("[PID %RU32]: Waiting for shutting down thread returned error rc=%Rrc\n",
     231                         pProcess->uPID, rc);
     232    }
     233    else
     234    {
     235        VBoxServiceVerbose(3, "[PID %RU32]: Thread reported exit code=%Rrc\n",
     236                           pProcess->uPID, rcThread);
     237        if (pRc)
     238            *pRc = rcThread;
    235239    }
    236240
     
    392396
    393397/**
    394  * Signals the given request.
     398 * Completes the given request. After returning pRequest won't be valid
     399 * anymore!
    395400 *
    396401 * @return  IPRT status code.
     
    398403 * @param   rc                      rc to set request result to.
    399404 */
    400 static int gstcntlProcessSignalRequest(PVBOXSERVICECTRLREQUEST pRequest, int rc)
     405static int gstcntlProcessRequestComplete(PVBOXSERVICECTRLREQUEST pRequest, int rc)
    401406{
    402407    AssertPtrReturn(pRequest, VERR_INVALID_POINTER);
    403408
    404     /* Assign overall result. */
    405     pRequest->rc = rc;
     409    int rc2;
     410    if (!pRequest->fAsync)
     411    {
     412        /* Assign overall result. */
     413        pRequest->rc = rc;
    406414
    407415#ifdef DEBUG_andy
    408     VBoxServiceVerbose(4, "Handled req=%RU32, CID=%RU32, rc=%Rrc, cbData=%RU32, pvData=%p\n",
    409                        pRequest->enmType, pRequest->uCID, pRequest->rc,
    410                        pRequest->cbData, pRequest->pvData);
     416        VBoxServiceVerbose(4, "Handled req=%RU32, CID=%RU32, rc=%Rrc, cbData=%RU32, pvData=%p\n",
     417                           pRequest->enmType, pRequest->uCID, pRequest->rc,
     418                           pRequest->cbData, pRequest->pvData);
    411419#endif
    412 
    413     /* In any case, regardless of the result, we notify
    414      * the main guest control to unblock it. */
    415     int rc2 = RTSemEventMultiSignal(pRequest->Event);
    416     AssertRC(rc2);
     420        /* Signal waiters. */
     421        rc2 = RTSemEventMultiSignal(pRequest->Event);
     422        AssertRC(rc2);
     423
     424        pRequest = NULL;
     425    }
     426    else
     427    {
     428#ifdef DEBUG_andy
     429        VBoxServiceVerbose(4, "Deleting async req=%RU32, CID=%RU32, rc=%Rrc, cbData=%RU32, pvData=%p\n",
     430                           pRequest->enmType, pRequest->uCID, pRequest->rc,
     431                           pRequest->cbData, pRequest->pvData);
     432#endif
     433        GstCntlProcessRequestFree(pRequest);
     434        rc2 = VINF_SUCCESS;
     435    }
    417436
    418437    return rc2;
     
    420439
    421440
    422 static int gstcntlProcessHandleRequest(RTPOLLSET hPollSet, uint32_t fPollEvt,
     441static int gstcntlProcessRequestHandle(RTPOLLSET hPollSet, uint32_t fPollEvt,
    423442                                       PRTPIPE phStdInW, PRTPIPE phStdOutR, PRTPIPE phStdErrR,
    424443                                       PVBOXSERVICECTRLPROCESS pProcess, PVBOXSERVICECTRLREQUEST pRequest)
     
    445464    switch (pRequest->enmType)
    446465    {
    447         case VBOXSERVICECTRLREQUEST_QUIT: /* Main control asked us to quit. */
    448         {
    449             /** @todo Check for some conditions to check to
    450              *        veto quitting. */
    451             ASMAtomicXchgBool(&pProcess->fShutdown, true);
    452             rcReq = VERR_CANCELLED;
    453             break;
    454         }
    455 
    456466        case VBOXSERVICECTRLREQUEST_PROC_STDIN:
    457467        case VBOXSERVICECTRLREQUEST_PROC_STDIN_EOF:
     
    532542        || !fDefer)
    533543    {
    534         rc = gstcntlProcessSignalRequest(pRequest,
    535                                          RT_SUCCESS(rc) ? rcReq : rc);
    536 
    537         /* No access to pRequest here anymore -- could be out of scope
    538          * or modified already! */
    539         pProcess->pRequest = pRequest = NULL;
     544        rc = gstcntlProcessRequestComplete(pRequest,
     545                                           RT_SUCCESS(rc) ? rcReq : rc);
    540546    }
    541547    else /* Completing the request defered. */
     
    641647                case VBOXSERVICECTRLPIPEID_IPC_NOTIFY:
    642648                    pReq = pProcess->pRequest; /** @todo Implement request queue. */
    643                     rc = gstcntlProcessHandleRequest(hPollSet, fPollEvt,
     649                    rc = gstcntlProcessRequestHandle(hPollSet, fPollEvt,
    644650                                                     phStdInW, phStdOutR, phStdErrR,
    645651                                                     pProcess, pReq);
    646                     if (rc != VINF_AIO_TASK_PENDING)
    647                         pReq = NULL;
     652                    if (rc == VINF_AIO_TASK_PENDING)
     653                        VBoxServiceVerbose(4, "[PID %RU32]: pRequest=%p will be handled deferred\n",
     654                                           pProcess->uPID, pReq);
    648655                    break;
    649656
     
    660667                           pProcess->uPID, rc2, RTPollSetGetCount(hPollSet), idPollHnd, rc, fProcessAlive, pProcess->fShutdown);
    661668#endif
    662 
    663669        if (RT_UNLIKELY(pProcess->fShutdown))
    664670            break; /* We were asked to shutdown. */
     
    791797            && pReq->enmType == VBOXSERVICECTRLREQUEST_PROC_TERM)
    792798        {
    793             rc2 = gstcntlProcessSignalRequest(pReq,
    794                                               fProcessAlive ? VINF_SUCCESS : VERR_PROCESS_RUNNING);
    795             pReq = NULL;
     799            rc2 = gstcntlProcessRequestComplete(pReq,
     800                                                fProcessAlive ? VINF_SUCCESS : VERR_PROCESS_RUNNING);
     801            AssertRC(rc2);
    796802        }
    797803        else if (pReq)
     
    878884                VBoxServiceError("[PID %RU32]: Error reporting final status to host; rc=%Rrc\n",
    879885                                 pProcess->uPID, rc2);
    880             if (RT_SUCCESS(rc))
    881                 rc = rc2;
    882886        }
    883887        else
    884888            VBoxServiceVerbose(3, "[PID %RU32]: Was started detached, no final status sent to host\n",
    885889                               pProcess->uPID);
    886 
    887         VBoxServiceVerbose(3, "[PID %RU32]: Process loop ended with rc=%Rrc\n",
    888                            pProcess->uPID, rc);
    889     }
    890     else
    891         VBoxServiceError("[PID %RU32]: Loop failed with rc=%Rrc\n",
    892                          pProcess->uPID, rc);
     890    }
     891
     892    VBoxServiceVerbose(3, "[PID %RU32]: Process loop ended with rc=%Rrc\n",
     893                       pProcess->uPID, rc);
    893894    return rc;
    894895}
     
    934935    AssertPtrReturn(ppReq, VERR_INVALID_POINTER);
    935936
    936     PVBOXSERVICECTRLREQUEST pReq = (PVBOXSERVICECTRLREQUEST)RTMemAlloc(sizeof(VBOXSERVICECTRLREQUEST));
     937    PVBOXSERVICECTRLREQUEST pReq =
     938        (PVBOXSERVICECTRLREQUEST)RTMemAlloc(sizeof(VBOXSERVICECTRLREQUEST));
    937939    AssertPtrReturn(pReq, VERR_NO_MEMORY);
    938940
    939941    RT_ZERO(*pReq);
     942    pReq->fAsync  = false;
    940943    pReq->enmType = enmType;
    941944    pReq->uCID    = uCID;
     
    16561659                                    VBoxServiceError("Error starting process, rc=%Rrc\n", rc);
    16571660                                /*
    1658                                  * Tell the control thread that it can continue
    1659                                  * spawning services. This needs to be done after the new
     1661                                 * Tell the session thread that it can continue
     1662                                 * spawning guest processes. This needs to be done after the new
    16601663                                 * process has been started because otherwise signal handling
    16611664                                 * on (Open) Solaris does not work correctly (see @bugref{5068}).
     
    17291732
    17301733    /* Move thread to stopped thread list. */
    1731     int rc2 = GstCntlSessionListSet(pProcess->pSession,
     1734    /*int rc2 = GstCntlSessionListSet(pProcess->pSession,
    17321735                                    pProcess, VBOXSERVICECTRLTHREADLIST_STOPPED);
    1733     AssertRC(rc2);
     1736    AssertRC(rc2);*/
    17341737
    17351738    if (pProcess->uClientID)
     
    17381741        {
    17391742            VBGLR3GUESTCTRLCMDCTX ctx = { pProcess->uClientID, pProcess->uContextID };
    1740             rc2 = VbglR3GuestCtrlProcCbStatus(&ctx,
    1741                                               pProcess->uPID, PROC_STS_ERROR, rc,
    1742                                               NULL /* pvData */, 0 /* cbData */);
     1743            int rc2 = VbglR3GuestCtrlProcCbStatus(&ctx,
     1744                                                  pProcess->uPID, PROC_STS_ERROR, rc,
     1745                                                  NULL /* pvData */, 0 /* cbData */);
    17431746            if (RT_FAILURE(rc2))
    17441747                VBoxServiceError("Could not report process failure error; rc=%Rrc (process error %Rrc)\n",
     
    17541757    }
    17551758
    1756     VBoxServiceVerbose(3, "[PID %RU32]: Thread of process \"%s\" ended with rc=%Rrc\n",
    1757                        pProcess->uPID, pProcess->StartupInfo.szCmd, rc);
    1758 
    17591759    /* Free argument + environment variable lists. */
    17601760    if (uNumEnvVars)
     
    17671767        RTGetOptArgvFree(papszArgs);
    17681768
    1769     /* Update started/stopped status. */
     1769    /* Update stopped status. */
    17701770    ASMAtomicXchgBool(&pProcess->fStopped, true);
    1771     ASMAtomicXchgBool(&pProcess->fStarted, false);
    17721771
    17731772    /*
     
    17781777        RTThreadUserSignal(RTThreadSelf());
    17791778
    1780     VBoxServiceVerbose(3, "[PID %RU32]: Thread returned with rc=%Rrc\n",
    1781                        pProcess->uPID, rc);
     1779    VBoxServiceVerbose(3, "[PID %RU32]: Thread of process \"%s\" ended with rc=%Rrc\n",
     1780                       pProcess->uPID, pProcess->StartupInfo.szCmd, rc);
    17821781    return rc;
    17831782}
     
    18751874 */
    18761875int GstCntlProcessPerform(PVBOXSERVICECTRLPROCESS pProcess,
    1877                           PVBOXSERVICECTRLREQUEST pRequest)
     1876                          PVBOXSERVICECTRLREQUEST pRequest,
     1877                          bool                    fAsync)
    18781878{
    18791879    AssertPtrReturn(pProcess, VERR_INVALID_POINTER);
     
    18831883
    18841884    int rc = VINF_SUCCESS;
     1885
     1886    AssertMsgReturn(pProcess->pRequest == NULL,
     1887                    ("Another request still is in progress (%p)\n", pProcess->pRequest),
     1888                    VERR_ACCESS_DENIED);
    18851889
    18861890    if (ASMAtomicReadBool(&pProcess->fShutdown))
     
    19081912        {
    19091913            Assert(cbWritten);
    1910             VBoxServiceVerbose(3, "[PID %RU32]: Waiting for response on pRequest=%p, enmType=%u, pvData=0x%p, cbData=%u\n",
    1911                                pProcess->uPID, pRequest, pRequest->enmType, pRequest->pvData, pRequest->cbData);
    1912 
    1913             rc = GstCntlProcessRequestWait(pRequest);
     1914            if (!fAsync)
     1915            {
     1916                VBoxServiceVerbose(3, "[PID %RU32]: Waiting for response on pRequest=%p, enmType=%u, pvData=0x%p, cbData=%u\n",
     1917                                   pProcess->uPID, pRequest, pRequest->enmType, pRequest->pvData, pRequest->cbData);
     1918
     1919                rc = GstCntlProcessRequestWait(pRequest);
     1920                if (RT_SUCCESS(rc))
     1921                    pProcess->pRequest = NULL;
     1922            }
    19141923        }
    19151924    }
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp

    r45415 r45604  
    820820            if (pProcess)
    821821            {
    822                 rc = GstCntlProcessPerform(pProcess, pRequest);
     822                rc = GstCntlProcessPerform(pProcess, pRequest, false /* Async */);
    823823                GstCntlProcessRelease(pProcess);
    824824            }
     
    855855            if (pProcess)
    856856            {
    857                 rc = GstCntlProcessPerform(pProcess, pRequest);
     857                rc = GstCntlProcessPerform(pProcess, pRequest, false /* Async */);
    858858                GstCntlProcessRelease(pProcess);
    859859            }
     
    10241024    if (RT_SUCCESS(rc))
    10251025    {
    1026         uint32_t uTimeoutsMS = 30 * 1000; /** @todo Make this configurable. Later. */
     1026        uint32_t uTimeoutsMS = 5 * 60 * 1000; /** @todo Make this configurable. Later. */
    10271027        uint64_t u64TimeoutStart = 0;
    10281028
     
    13041304         * Close all guest processes.
    13051305         */
     1306        VBoxServiceVerbose(0, "Stopping all guest processes ...\n");
    13061307
    13071308        /* Signal all guest processes in the active list that we want to shutdown. */
     
    13101311            GstCntlProcessStop(pProcess);
    13111312
     1313        VBoxServiceVerbose(1, "All guest processes signalled to stop\n");
     1314
    13121315        /* Wait for all active threads to shutdown and destroy the active thread list. */
    13131316        pProcess = RTListGetFirst(&pSession->lstProcessesActive, VBOXSERVICECTRLPROCESS, Node);
     
    13281331            }
    13291332
     1333            RTListNodeRemove(&pProcess->Node);
     1334
    13301335            rc2 = GstCntlProcessFree(pProcess);
    13311336            if (RT_FAILURE(rc2))
     
    13371342            }
    13381343
    1339             RTListNodeRemove(&pProcess->Node);
    1340 
    13411344            if (fLast)
    13421345                break;
     
    13571360         * Close all left guest files.
    13581361         */
     1362        VBoxServiceVerbose(0, "Closing all guest files ...\n");
     1363
    13591364        PVBOXSERVICECTRLFILE pFile;
    13601365        pFile = RTListGetFirst(&pSession->lstFiles, VBOXSERVICECTRLFILE, Node);
     
    14271432    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
    14281433    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
    1429     AssertPtrNullReturn(pcbRead, VERR_INVALID_POINTER);
     1434    /* pcbRead is optional. */
    14301435
    14311436    int                         rc      = VINF_SUCCESS;
     
    14561461            if (pProcess)
    14571462            {
    1458                 rc = GstCntlProcessPerform(pProcess, pRequest);
     1463                rc = GstCntlProcessPerform(pProcess, pRequest, false /* Async */);
    14591464                GstCntlProcessRelease(pProcess);
    14601465            }
     
    17001705        if (pProcess)
    17011706        {
    1702             rc = GstCntlProcessPerform(pProcess, pRequest);
     1707            rc = GstCntlProcessPerform(pProcess, pRequest, false /* Async */);
    17031708            GstCntlProcessRelease(pProcess);
    17041709        }
     
    20902095    /*
    20912096     * The fork should have received the same closing request,
    2092      * so just wait 30s for the process to close. On timeout kill
    2093      * it in a not so gentle manner.
     2097     * so just wait for the process to close.
    20942098     */
    20952099    if (ASMAtomicReadBool(&pThread->fStarted))
     
    21292133
    21302134    int rc = GstCntlSessionThreadWait(pThread,
    2131                                       30 * 1000 /* 30s timeout */, uFlags);
     2135                                      5 * 60 * 1000 /* 5 minutes timeout */, uFlags);
    21322136    /** @todo Kill session process if still around? */
    21332137
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