VirtualBox

Changeset 47469 in vbox for trunk/src


Ignore:
Timestamp:
Jul 30, 2013 9:43:14 AM (11 years ago)
Author:
vboxsync
Message:

Guest Control: Adjustments for supporting < 4.3 Guest Additions in conjunction with the new guest session, extended testcase (now passing using latest 4.2 Guest Additions with latest trunk).

Location:
trunk/src/VBox/Main
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r47401 r47469  
    95879587      <desc>
    95889588        A guest user currently is not using the guest OS.
    9589         <note>Currently only available for Windows guests since 
     9589        <note>Currently only available for Windows guests since
    95909590          Windows 2000 SP2.</note>
    95919591        <note>On Windows guests this function currently only supports
     
    95959595        VBoxService's command line on the guest to
    95969596        <pre>--vminfo-user-idle-threshold &lt;ms&gt;</pre>
    9597         , or by setting the per-VM guest property 
     9597        , or by setting the per-VM guest property
    95989598        <pre>/VirtualBox/GuestAdd/VBoxService/--vminfo-user-idle-threshold &lt;ms&gt;</pre>
    95999599        with the RDONLYGUEST flag on the host. In both cases VBoxService needs
     
    96029602    </const>
    96039603    <const name="InUse"                   value="7">
    9604       <desc>A guest user continued using the guest OS after 
     9604      <desc>A guest user continued using the guest OS after
    96059605        being idle.</desc>
    96069606    </const>
     
    1013510135  <interface
    1013610136    name="IGuestSession" extends="$unknown"
    10137     uuid="c8e8607b-5e67-4073-8f14-146515d0c1ff"
     10137    uuid="1afeabbd-0c0b-458c-8026-04464892ae12"
    1013810138    wsmap="managed"
    1013910139    >
     
    1018310183        </result>
    1018410184      </desc>
     10185    </attribute>
     10186    <attribute name="protocolVersion" type="unsigned long" readonly="yes">
     10187      <desc>Returns the protocol version which is used by this session to
     10188        communicate with the guest.</desc>
    1018510189    </attribute>
    1018610190    <attribute name="status" type="GuestSessionStatus" readonly="yes">
  • trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h

    r45780 r47469  
    377377class GuestWaitEvent
    378378{
     379
    379380public:
    380381
     
    387388    const ComPtr<IEvent>             Event(void) { return mEvent; };
    388389    const std::list<VBoxEventType_T> Types(void) { return mEventTypes; };
    389     int                              Signal(IEvent *pEvent);
     390    virtual int                      Signal(IEvent *pEvent);
    390391    int                              Wait(RTMSINTERVAL uTimeoutMS);
    391392
    392393protected:
    393394
     395    /* Shutdown indicator. */
     396    bool                       fAborted;
     397    /* Associated context ID (CID). */
    394398    uint32_t                   mCID;
     399    /** List of event types this event should
     400     *  be signalled on. */
    395401    std::list<VBoxEventType_T> mEventTypes;
    396402    /** The event semaphore for triggering
     
    418424public:
    419425
     426    int baseInit(void);
     427    void baseUninit(void);
     428    int cancelWaitEvents(void);
    420429    int generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID);
    421     int registerEvent(uint32_t uSessionID, uint32_t uObjectID, const std::list<VBoxEventType_T> &lstEvents, GuestWaitEvent **ppEvent);
    422     void unregisterEvent(GuestWaitEvent *pEvent);
    423     void unregisterEventListener(void);
     430    int registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, const std::list<VBoxEventType_T> &lstEvents, GuestWaitEvent **ppEvent);
     431    void unregisterWaitEvent(GuestWaitEvent *pEvent);
    424432    int waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, VBoxEventType_T *pType, IEvent **ppEvent);
    425433
     
    431439    /** The next upcoming context ID for this object. */
    432440    uint32_t                 mNextContextID;
    433     /** Local listener for handling the waiting events. */
    434     ComPtr<IEventListener>   mListener;
     441    /** Local listener for handling the waiting events
     442     *  internally. */
     443    ComPtr<IEventListener>   mLocalListener;
    435444    /** Critical section for wait events access. */
    436445    RTCRITSECT               mWaitEventCritSect;
     
    463472
    464473    int bindToSession(Console *pConsole, GuestSession *pSession, uint32_t uObjectID);
    465     int registerEvent(const std::list<VBoxEventType_T> &lstEvents, GuestWaitEvent **ppEvent);
     474    int registerWaitEvent(const std::list<VBoxEventType_T> &lstEvents, GuestWaitEvent **ppEvent);
    466475    int sendCommand(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms);
    467476
  • trunk/src/VBox/Main/include/GuestProcessImpl.h

    r45780 r47469  
    8080    int readData(uint32_t uHandle, uint32_t uSize, uint32_t uTimeoutMS, void *pvData, size_t cbData, uint32_t *pcbRead, int *pGuestRc);
    8181    static HRESULT setErrorExternal(VirtualBoxBase *pInterface, int guestRc);
    82     int startProcess(int *pGuestRc);
     82    int startProcess(uint32_t uTimeoutMS, int *pGuestRc);
    8383    int startProcessAsync(void);
    84     int terminateProcess(int *pGuestRc);
     84    int terminateProcess(uint32_t uTimeoutMS, int *pGuestRc);
     85    static ProcessWaitResult_T waitFlagsToResultEx(uint32_t fWaitFlags, ProcessStatus_T procStatus, uint32_t uProcFlags, uint32_t uProtocol);
     86    ProcessWaitResult_T waitFlagsToResult(uint32_t fWaitFlags);
    8587    int waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc);
    8688    int waitForInputNotify(GuestWaitEvent *pEvent, uint32_t uHandle, uint32_t uTimeoutMS, ProcessInputStatus_T *pInputStatus, uint32_t *pcbProcessed);
    8789    int waitForOutput(GuestWaitEvent *pEvent, uint32_t uHandle, uint32_t uTimeoutMS, void* pvData, size_t cbData, uint32_t *pcbRead);
    88     int waitForStatusChange(GuestWaitEvent *pEvent, uint32_t fWaitFlags, uint32_t uTimeoutMS, ProcessStatus_T *pProcessStatus, int *pGuestRc);
     90    int waitForStatusChange(GuestWaitEvent *pEvent, uint32_t uTimeoutMS, ProcessStatus_T *pProcessStatus, int *pGuestRc);
     91    static bool waitResultImpliesEx(ProcessWaitResult_T waitResult, ProcessStatus_T procStatus, uint32_t uProcFlags, uint32_t uProtocol);
    8992    int writeData(uint32_t uHandle, uint32_t uFlags, void *pvData, size_t cbData, uint32_t uTimeoutMS, uint32_t *puWritten, int *pGuestRc);
    9093    /** @}  */
     
    168171    int TerminatedOk(LONG *pExitCode);
    169172
    170     void Terminate(void);
     173    int Terminate(uint32_t uTimeoutMS, int *pGuestRc);
    171174
    172175protected:
  • trunk/src/VBox/Main/include/GuestSessionImpl.h

    r46524 r47469  
    273273    STDMETHOD(COMGETTER(Timeout))(ULONG *aTimeout);
    274274    STDMETHOD(COMSETTER(Timeout))(ULONG aTimeout);
     275    STDMETHOD(COMGETTER(ProtocolVersion))(ULONG *aVersion);
    275276    STDMETHOD(COMGETTER(Environment))(ComSafeArrayOut(BSTR, aEnvironment));
    276277    STDMETHOD(COMSETTER(Environment))(ComSafeArrayIn(IN_BSTR, aEnvironment));
     
    359360    HRESULT                 isReadyExternal(void);
    360361    int                     onSessionStatusChange(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData);
    361     int                     startSessionIntenal(int *pGuestRc);
     362    int                     startSessionInternal(int *pGuestRc);
    362363    int                     startSessionAsync(void);
    363364    static DECLCALLBACK(int)
     
    384385    Guest                          *mParent;
    385386    /**
    386      * This can safely be used without holding any locks.
     387     * The session's event source. This source is used for
     388     * serving the internal listener as well as all other
     389     * external listeners that may register to it.
     390     *
     391     * Note: This can safely be used without holding any locks.
    387392     * An AutoCaller suffices to prevent it being destroy while in use and
    388393     * internally there is a lock providing the necessary serialization.
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r46526 r47469  
    115115#endif /* VBOX_WITH_GUEST_CONTROL */
    116116
    117 STDMETHODIMP Guest::UpdateGuestAdditions(IN_BSTR aSource, ComSafeArrayIn(IN_BSTR, aArguments), 
     117STDMETHODIMP Guest::UpdateGuestAdditions(IN_BSTR aSource, ComSafeArrayIn(IN_BSTR, aArguments),
    118118                                         ComSafeArrayIn(AdditionsUpdateFlag_T, aFlags), IProgress **aProgress)
    119119{
     
    194194        Assert(!pSession.isNull());
    195195        int guestRc;
    196         rc = pSession->startSessionIntenal(&guestRc);
     196        rc = pSession->startSessionInternal(&guestRc);
    197197        if (RT_FAILURE(rc))
    198198        {
     
    341341        if (pSession == itSessions->second)
    342342        {
     343            GuestSession *pCurSession = itSessions->second;
     344            AssertPtr(pCurSession);
     345
    343346            LogFlowFunc(("Removing session (pSession=%p, ID=%RU32) (now total %ld sessions)\n",
    344                          (GuestSession *)itSessions->second, itSessions->second->getId(), mData.mGuestSessions.size() - 1));
     347                         pCurSession, pCurSession->getId(), mData.mGuestSessions.size() - 1));
     348
     349            itSessions->second->Release();
    345350
    346351            mData.mGuestSessions.erase(itSessions);
     
    458463    if (RT_UNLIKELY((aUser) == NULL || *(aUser) == '\0'))
    459464        return setError(E_INVALIDARG, tr("No user name specified"));
     465    if (RT_UNLIKELY((aPassword) == NULL || *(aPassword) == '\0'))
     466        return setError(E_INVALIDARG, tr("No password specified"));
    460467    CheckComArgOutPointerValid(aGuestSession);
    461468    /* Rest is optional. */
  • trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp

    r45801 r47469  
    2525
    2626#include <iprt/asm.h>
     27#include <iprt/cpp/utils.h> /* For unconst(). */
    2728#include <iprt/ctype.h>
    2829#ifdef DEBUG
     
    788789}
    789790
     791int GuestBase::baseInit(void)
     792{
     793    int rc = RTCritSectInit(&mWaitEventCritSect);
     794
     795    LogFlowFuncLeaveRC(rc);
     796    return rc;
     797}
     798
     799void GuestBase::baseUninit(void)
     800{
     801    LogFlowThisFuncEnter();
     802
     803    int rc = RTCritSectDelete(&mWaitEventCritSect);
     804
     805    LogFlowFuncLeaveRC(rc);
     806    /* No return value. */
     807}
     808
     809int GuestBase::cancelWaitEvents(void)
     810{
     811    LogFlowThisFuncEnter();
     812
     813    int rc = RTCritSectEnter(&mWaitEventCritSect);
     814    if (RT_SUCCESS(rc))
     815    {
     816        GuestWaitEventTypes::iterator itEventTypes = mWaitEvents.begin();
     817        while (itEventTypes != mWaitEvents.end())
     818        {
     819            GuestWaitEvents::iterator itEvents = itEventTypes->second.begin();
     820            while (itEvents != itEventTypes->second.end())
     821            {
     822                GuestWaitEvent *pEvent = (*itEvents);
     823                AssertPtr(pEvent);
     824
     825                /*
     826                 * Just cancel the event and remove it from the wait events
     827                 * map. Don't delete it though, this (hopefully) is done by
     828                 * the caller using unregisterWaitEvent().
     829                 */
     830                int rc2 = pEvent->Signal(NULL /* Cancel */);
     831                AssertRC(rc2);
     832                itEvents = itEventTypes->second.erase(itEvents);
     833            }
     834
     835            itEventTypes = mWaitEvents.erase(itEventTypes);
     836        }
     837
     838        int rc2 = RTCritSectLeave(&mWaitEventCritSect);
     839        if (RT_SUCCESS(rc))
     840            rc = rc2;
     841    }
     842
     843    LogFlowFuncLeaveRC(rc);
     844    return rc;
     845}
     846
    790847int GuestBase::generateContextID(uint32_t uSessionID, uint32_t uObjectID, uint32_t *puContextID)
    791848{
    792849    AssertPtrReturn(puContextID, VERR_INVALID_POINTER);
    793850
    794     uint32_t uCount = mNextContextID++;
     851    uint32_t uCount = ASMAtomicIncU32(&mNextContextID);
    795852    if (uCount == VBOX_GUESTCTRL_MAX_CONTEXTS)
    796853        uCount = 0;
     
    804861}
    805862
    806 int GuestBase::registerEvent(uint32_t uSessionID, uint32_t uObjectID,
    807                              const std::list<VBoxEventType_T> &lstEvents,
    808                              GuestWaitEvent **ppEvent)
     863int GuestBase::registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID,
     864                                 const std::list<VBoxEventType_T> &lstEvents,
     865                                 GuestWaitEvent **ppEvent)
    809866{
    810867    AssertPtrReturn(ppEvent, VERR_INVALID_POINTER);
     
    871928}
    872929
    873 void GuestBase::unregisterEvent(GuestWaitEvent *pEvent)
    874 {
    875     AssertPtrReturnVoid(pEvent);
     930void GuestBase::unregisterWaitEvent(GuestWaitEvent *pEvent)
     931{
     932    if (!pEvent) /* Nothing to unregister. */
     933        return;
    876934
    877935    int rc = RTCritSectEnter(&mWaitEventCritSect);
     
    897955
    898956        delete pEvent;
     957        pEvent = NULL;
    899958
    900959        int rc2 = RTCritSectLeave(&mWaitEventCritSect);
     
    904963}
    905964
    906 void GuestBase::unregisterEventListener(void)
    907 {
    908     if (mListener)
    909     {
    910         ComPtr<IEventSource> es;
    911         HRESULT hr = mConsole->COMGETTER(EventSource)(es.asOutParam());
    912         if (SUCCEEDED(hr))
    913         {
    914             Assert(!es.isNull());
    915             es->UnregisterListener(mListener);
    916         }
    917 
    918         mListener.setNull();
    919     }
    920 
    921     int rc2 = RTCritSectDelete(&mWaitEventCritSect);
    922     AssertRC(rc2);
    923 }
    924 
    925965int GuestBase::waitForEvent(GuestWaitEvent *pEvent, uint32_t uTimeoutMS,
    926966                            VBoxEventType_T *pType, IEvent **ppEvent)
     
    943983                vrc = VERR_COM_UNEXPECTED;
    944984        }
    945         if (ppEvent)
     985        if (   RT_SUCCESS(vrc)
     986            && ppEvent)
    946987            pThisEvent.queryInterfaceTo(ppEvent);
     988
     989        unconst(pThisEvent).setNull();
    947990    }
    948991
     
    9731016}
    9741017
    975 int GuestObject::registerEvent(const std::list<VBoxEventType_T> &lstEvents,
    976                                GuestWaitEvent **ppEvent)
     1018int GuestObject::registerWaitEvent(const std::list<VBoxEventType_T> &lstEvents,
     1019                                   GuestWaitEvent **ppEvent)
    9771020{
    9781021    AssertPtr(mSession);
    979     return GuestBase::registerEvent(mSession->getId(), mObjectID, lstEvents, ppEvent);
     1022    return GuestBase::registerWaitEvent(mSession->getId(), mObjectID, lstEvents, ppEvent);
    9801023}
    9811024
     
    10091052GuestWaitEvent::GuestWaitEvent(uint32_t uCID,
    10101053                               const std::list<VBoxEventType_T> &lstEvents)
    1011     : mCID(uCID),
     1054    : fAborted(false),
     1055      mCID(uCID),
    10121056      mEventTypes(lstEvents),
    10131057      mEventSem(NIL_RTSEMEVENT)
     
    10231067}
    10241068
     1069/**
     1070 * Signals the event. Passing NULL will abort (cancel)
     1071 * the event.
     1072 *
     1073 * @return  IPRT status code.
     1074 * @param   pEvent              IEvent to associate.
     1075 */
    10251076int GuestWaitEvent::Signal(IEvent *pEvent)
    10261077{
    1027     AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
    10281078    AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED);
    10291079
    1030     mEvent = pEvent;
     1080    if (pEvent)
     1081        mEvent = pEvent;
     1082    else
     1083        ASMAtomicWriteBool(&fAborted, true);
    10311084
    10321085    return RTSemEventSignal(mEventSem);
     
    10351088int GuestWaitEvent::Wait(RTMSINTERVAL uTimeoutMS)
    10361089{
    1037     LogFlowThisFuncEnter();
    1038 
    1039     AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED);
    1040 
    1041     RTMSINTERVAL msInterval = uTimeoutMS;
    1042     if (!uTimeoutMS)
    1043         msInterval = RT_INDEFINITE_WAIT;
    1044     int rc = RTSemEventWait(mEventSem, msInterval);
     1090    LogFlowThisFunc(("uTimeoutMS=%RU32ms\n", uTimeoutMS));
     1091
     1092    int rc = VINF_SUCCESS;
     1093
     1094    if (ASMAtomicReadBool(&fAborted))
     1095        rc = VERR_CANCELLED;
     1096
     1097    if (RT_SUCCESS(rc))
     1098    {
     1099        AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED);
     1100
     1101        RTMSINTERVAL msInterval = uTimeoutMS;
     1102        if (!uTimeoutMS)
     1103            msInterval = RT_INDEFINITE_WAIT;
     1104        rc = RTSemEventWait(mEventSem, msInterval);
     1105        if (ASMAtomicReadBool(&fAborted))
     1106            rc = VERR_CANCELLED;
     1107    }
    10451108
    10461109    LogFlowFuncLeaveRC(rc);
  • trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp

    r45078 r47469  
    22/* $Id$ */
    33/** @file
    4  * VirtualBox Main - XXX.
     4 * VirtualBox Main - Guest directory handling.
    55 */
    66
    77/*
    8  * Copyright (C) 2012 Oracle Corporation
     8 * Copyright (C) 2012-2013 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    178178    AssertPtr(mData.mSession);
    179179    int rc = mData.mSession->directoryRemoveFromList(this);
    180 
    181     mData.mProcessTool.Terminate();
     180    AssertRC(rc);
     181
     182    HRESULT hr = S_OK;
     183
     184    int guestRc;
     185    rc = mData.mProcessTool.Terminate(30 * 1000, &guestRc);
     186    if (RT_FAILURE(rc))
     187    {
     188        switch (rc)
     189        {
     190           case VERR_GSTCTL_GUEST_ERROR:
     191                hr = GuestProcess::setErrorExternal(this, guestRc);
     192                break;
     193
     194            case VERR_NOT_SUPPORTED:
     195                /* Silently skip old Guest Additions which do not support killing the
     196                 * the guest directory handling process. */
     197                break;
     198
     199            default:
     200                hr = setError(VBOX_E_IPRT_ERROR,
     201                              tr("Terminating open guest directory \"%s\" failed: %Rrc"),
     202                              mData.mName.c_str(), rc);
     203                break;
     204        }
     205    }
    182206
    183207    /*
     
    189213
    190214    LogFlowFuncLeaveRC(rc);
    191     return S_OK;
     215    return hr;
    192216#endif /* VBOX_WITH_GUEST_CONTROL */
    193217}
  • trunk/src/VBox/Main/src-client/GuestFileImpl.cpp

    r45805 r47469  
    175175            if (SUCCEEDED(hr))
    176176            {
    177                 mListener = thisListener;
    178 
    179177                com::SafeArray <VBoxEventType_T> eventTypes;
    180178                eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
     
    182180                eventTypes.push_back(VBoxEventType_OnGuestFileRead);
    183181                eventTypes.push_back(VBoxEventType_OnGuestFileWrite);
    184                 hr = mEventSource->RegisterListener(mListener,
     182                hr = mEventSource->RegisterListener(thisListener,
    185183                                                    ComSafeArrayAsInParam(eventTypes),
    186184                                                    TRUE /* Active listener */);
    187185                if (SUCCEEDED(hr))
    188186                {
    189                     vrc = RTCritSectInit(&mWaitEventCritSect);
    190                     AssertRC(vrc);
     187                    vrc = baseInit();
     188                    if (RT_SUCCESS(vrc))
     189                    {
     190                        mLocalListener = thisListener;
     191                    }
    191192                }
    192193                else
     
    229230
    230231#ifdef VBOX_WITH_GUEST_CONTROL
     232    baseUninit();
     233
     234    mEventSource->UnregisterListener(mLocalListener);
    231235    unconst(mEventSource).setNull();
    232     unregisterEventListener();
    233236#endif
    234237
     
    432435        eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
    433436
    434         vrc = registerEvent(eventTypes, &pEvent);
     437        vrc = registerWaitEvent(eventTypes, &pEvent);
    435438    }
    436439    catch (std::bad_alloc)
     
    452455        vrc = waitForStatusChange(pEvent, 30 * 1000 /* Timeout in ms */,
    453456                                  NULL /* FileStatus */);
    454     unregisterEvent(pEvent);
     457    unregisterWaitEvent(pEvent);
    455458
    456459    LogFlowFuncLeaveRC(vrc);
     
    711714        eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
    712715
    713         vrc = registerEvent(eventTypes, &pEvent);
     716        vrc = registerWaitEvent(eventTypes, &pEvent);
    714717    }
    715718    catch (std::bad_alloc)
     
    739742                                  NULL /* FileStatus */);
    740743
    741     unregisterEvent(pEvent);
     744    unregisterWaitEvent(pEvent);
    742745
    743746    LogFlowFuncLeaveRC(vrc);
     
    762765        eventTypes.push_back(VBoxEventType_OnGuestFileRead);
    763766
    764         vrc = registerEvent(eventTypes, &pEvent);
     767        vrc = registerWaitEvent(eventTypes, &pEvent);
    765768    }
    766769    catch (std::bad_alloc)
     
    792795    }
    793796
    794     unregisterEvent(pEvent);
     797    unregisterWaitEvent(pEvent);
    795798
    796799    LogFlowFuncLeaveRC(vrc);
     
    812815        eventTypes.push_back(VBoxEventType_OnGuestFileRead);
    813816
    814         vrc = registerEvent(eventTypes, &pEvent);
     817        vrc = registerWaitEvent(eventTypes, &pEvent);
    815818    }
    816819    catch (std::bad_alloc)
     
    843846    }
    844847
    845     unregisterEvent(pEvent);
     848    unregisterWaitEvent(pEvent);
    846849
    847850    LogFlowFuncLeaveRC(vrc);
     
    863866        eventTypes.push_back(VBoxEventType_OnGuestFileOffsetChanged);
    864867
    865         vrc = registerEvent(eventTypes, &pEvent);
     868        vrc = registerWaitEvent(eventTypes, &pEvent);
    866869    }
    867870    catch (std::bad_alloc)
     
    885888        vrc = waitForOffsetChange(pEvent, uTimeoutMS, puOffset);
    886889
    887     unregisterEvent(pEvent);
     890    unregisterWaitEvent(pEvent);
    888891
    889892    LogFlowFuncLeaveRC(vrc);
     
    10781081        eventTypes.push_back(VBoxEventType_OnGuestFileWrite);
    10791082
    1080         vrc = registerEvent(eventTypes, &pEvent);
     1083        vrc = registerWaitEvent(eventTypes, &pEvent);
    10811084    }
    10821085    catch (std::bad_alloc)
     
    11091112    }
    11101113
    1111     unregisterEvent(pEvent);
     1114    unregisterWaitEvent(pEvent);
    11121115
    11131116    LogFlowFuncLeaveRC(vrc);
     
    11321135        eventTypes.push_back(VBoxEventType_OnGuestFileWrite);
    11331136
    1134         vrc = registerEvent(eventTypes, &pEvent);
     1137        vrc = registerWaitEvent(eventTypes, &pEvent);
    11351138    }
    11361139    catch (std::bad_alloc)
     
    11641167    }
    11651168
    1166     unregisterEvent(pEvent);
     1169    unregisterWaitEvent(pEvent);
    11671170
    11681171    LogFlowFuncLeaveRC(vrc);
  • trunk/src/VBox/Main/src-client/GuestImpl.cpp

    r47310 r47469  
    110110
    111111#ifdef VBOX_WITH_GUEST_CONTROL
    112     unconst(mEventSource).createObject();
    113     Assert(!mEventSource.isNull());
    114     hr = mEventSource->init(static_cast<IGuest*>(this));
     112    hr = unconst(mEventSource).createObject();
     113    if (SUCCEEDED(hr))
     114        hr = mEventSource->init(static_cast<IGuest*>(this));
    115115#else
    116116    hr = S_OK;
  • trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp

    r45927 r47469  
    118118                int rc2 = mProcess->signalWaitEvents(aType, aEvent);
    119119#ifdef DEBUG_andy
    120                 LogFlowFunc(("Signalling events of type=%ld, process=%p resulted in rc=%Rrc\n",
    121                              aType, mProcess, rc2));
     120                LogFlowThisFunc(("Signalling events of type=%ld, process=%p resulted in rc=%Rrc\n",
     121                                 aType, mProcess, rc2));
    122122#endif
    123123                break;
     
    184184    if (RT_SUCCESS(vrc))
    185185    {
    186         unconst(mEventSource).createObject();
    187         Assert(!mEventSource.isNull());
    188         hr = mEventSource->init(static_cast<IGuestProcess*>(this));
     186        hr = unconst(mEventSource).createObject();
    189187        if (FAILED(hr))
    190             vrc = VERR_COM_UNEXPECTED;
     188            vrc = VERR_NO_MEMORY;
     189        else
     190        {
     191            hr = mEventSource->init(static_cast<IGuestProcess*>(this));
     192            if (FAILED(hr))
     193                vrc = VERR_COM_UNEXPECTED;
     194        }
    191195    }
    192196
     
    203207            if (SUCCEEDED(hr))
    204208            {
    205                 mListener = thisListener;
    206 
    207209                com::SafeArray <VBoxEventType_T> eventTypes;
    208210                eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
    209211                eventTypes.push_back(VBoxEventType_OnGuestProcessInputNotify);
    210212                eventTypes.push_back(VBoxEventType_OnGuestProcessOutput);
    211                 hr = mEventSource->RegisterListener(mListener,
     213                hr = mEventSource->RegisterListener(thisListener,
    212214                                                    ComSafeArrayAsInParam(eventTypes),
    213215                                                    TRUE /* Active listener */);
    214216                if (SUCCEEDED(hr))
    215217                {
    216                     vrc = RTCritSectInit(&mWaitEventCritSect);
    217                     AssertRC(vrc);
     218                    vrc = baseInit();
     219                    if (RT_SUCCESS(vrc))
     220                    {
     221                        mLocalListener = thisListener;
     222                    }
    218223                }
    219224                else
     
    255260void GuestProcess::uninit(void)
    256261{
    257     LogFlowThisFunc(("mCmd=%s, PID=%RU32\n",
    258                      mData.mProcess.mCommand.c_str(), mData.mPID));
     262    LogFlowThisFuncEnter();
    259263
    260264    /* Enclose the state transition Ready->InUninit->NotReady. */
     
    263267        return;
    264268
    265     int vrc = VINF_SUCCESS;
     269    LogFlowThisFunc(("mCmd=%s, PID=%RU32\n",
     270                     mData.mProcess.mCommand.c_str(), mData.mPID));
     271
     272    /* Terminate process if not already done yet. */
     273    int guestRc = VINF_SUCCESS;
     274    int vrc = terminateProcess(30 * 1000, &guestRc); /** @todo Make timeouts configurable. */
     275    /* Note: Don't return here yet; first uninit all other stuff in
     276     *       case of failure. */
    266277
    267278#ifdef VBOX_WITH_GUEST_CONTROL
     279    baseUninit();
     280
     281    mEventSource->UnregisterListener(mLocalListener);
     282
     283    mLocalListener.setNull();
    268284    unconst(mEventSource).setNull();
    269     unregisterEventListener();
    270285#endif
    271286
    272     LogFlowFuncLeaveRC(vrc);
     287    LogFlowThisFunc(("Returning rc=%Rrc, guestRc=%Rrc\n",
     288                     vrc, guestRc));
    273289}
    274290
     
    532548#ifndef DEBUG_andy
    533549        /* This should never happen! */
    534         AssertReleaseMsg(mData.mPID == uPID, ("Unterminated guest process (PID %RU32) sent data to a newly started process (PID %RU32)\n",
     550        AssertReleaseMsg(mData.mPID == uPID, ("Unterminated guest process (guest PID %RU32) sent data to a newly started process (host PID %RU32)\n",
    535551                                              uPID, mData.mPID));
    536552#endif
     
    665681
    666682    vrc = checkPID(dataCb.uPID);
    667     AssertRCReturn(vrc, vrc);
    668 
    669     ProcessInputStatus_T inputStatus = ProcessInputStatus_Undefined;
    670     switch (dataCb.uStatus)
    671     {
    672         case INPUT_STS_WRITTEN:
    673             inputStatus = ProcessInputStatus_Written;
    674             break;
    675         case INPUT_STS_ERROR:
    676             inputStatus = ProcessInputStatus_Broken;
    677             break;
    678         case INPUT_STS_TERMINATED:
    679             inputStatus = ProcessInputStatus_Broken;
    680             break;
    681         case INPUT_STS_OVERFLOW:
    682             inputStatus = ProcessInputStatus_Overflow;
    683             break;
    684         case INPUT_STS_UNDEFINED:
    685             /* Fall through is intentional. */
    686         default:
    687             AssertMsg(!dataCb.uProcessed, ("Processed data is not 0 in undefined input state\n"));
    688             break;
    689     }
    690 
    691     if (inputStatus != ProcessInputStatus_Undefined)
    692     {
    693         fireGuestProcessInputNotifyEvent(mEventSource, mSession, this,
    694                                          mData.mPID, 0 /* StdIn */, dataCb.uProcessed, inputStatus);
     683    if (RT_SUCCESS(vrc))
     684    {
     685        ProcessInputStatus_T inputStatus = ProcessInputStatus_Undefined;
     686        switch (dataCb.uStatus)
     687        {
     688            case INPUT_STS_WRITTEN:
     689                inputStatus = ProcessInputStatus_Written;
     690                break;
     691            case INPUT_STS_ERROR:
     692                inputStatus = ProcessInputStatus_Broken;
     693                break;
     694            case INPUT_STS_TERMINATED:
     695                inputStatus = ProcessInputStatus_Broken;
     696                break;
     697            case INPUT_STS_OVERFLOW:
     698                inputStatus = ProcessInputStatus_Overflow;
     699                break;
     700            case INPUT_STS_UNDEFINED:
     701                /* Fall through is intentional. */
     702            default:
     703                AssertMsg(!dataCb.uProcessed, ("Processed data is not 0 in undefined input state\n"));
     704                break;
     705        }
     706
     707        if (inputStatus != ProcessInputStatus_Undefined)
     708        {
     709            fireGuestProcessInputNotifyEvent(mEventSource, mSession, this,
     710                                             mData.mPID, 0 /* StdIn */, dataCb.uProcessed, inputStatus);
     711        }
    695712    }
    696713
     
    709726int GuestProcess::onProcessStatusChange(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
    710727{
    711     /* pCallback is optional. */
     728    AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
    712729    AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
    713730
     
    730747
    731748    vrc = checkPID(dataCb.uPID);
    732     AssertRCReturn(vrc, vrc);
    733 
    734     ProcessStatus_T procStatus = ProcessStatus_Undefined;
    735     int procRc = VINF_SUCCESS;
    736 
    737     switch (dataCb.uStatus)
    738     {
    739         case PROC_STS_STARTED:
    740         {
    741             procStatus = ProcessStatus_Started;
    742             mData.mPID = dataCb.uPID; /* Set the process PID. */
    743             break;
    744         }
    745 
    746         case PROC_STS_TEN:
    747         {
    748             procStatus = ProcessStatus_TerminatedNormally;
    749             mData.mExitCode = dataCb.uFlags; /* Contains the exit code. */
    750             break;
    751         }
    752 
    753         case PROC_STS_TES:
    754         {
    755             procStatus = ProcessStatus_TerminatedSignal;
    756             mData.mExitCode = dataCb.uFlags; /* Contains the signal. */
    757             break;
    758         }
    759 
    760         case PROC_STS_TEA:
    761         {
    762             procStatus = ProcessStatus_TerminatedAbnormally;
    763             break;
    764         }
    765 
    766         case PROC_STS_TOK:
    767         {
    768             procStatus = ProcessStatus_TimedOutKilled;
    769             break;
    770         }
    771 
    772         case PROC_STS_TOA:
    773         {
    774             procStatus = ProcessStatus_TimedOutAbnormally;
    775             break;
    776         }
    777 
    778         case PROC_STS_DWN:
    779         {
    780             procStatus = ProcessStatus_Down;
    781             break;
    782         }
    783 
    784         case PROC_STS_ERROR:
    785         {
    786             procRc = dataCb.uFlags; /* mFlags contains the IPRT error sent from the guest. */
    787             procStatus = ProcessStatus_Error;
    788             break;
    789         }
    790 
    791         case PROC_STS_UNDEFINED:
    792         default:
    793         {
    794             /* Silently skip this request. */
    795             procStatus = ProcessStatus_Undefined;
    796             break;
    797         }
    798     }
    799 
    800     LogFlowThisFunc(("Got rc=%Rrc, procSts=%ld, procRc=%Rrc\n",
    801                      vrc, procStatus, procRc));
    802 
    803     /* Set the process status. */
    804     int rc2 = setProcessStatus(procStatus, procRc);
    805749    if (RT_SUCCESS(vrc))
    806         vrc = rc2;
     750    {
     751        ProcessStatus_T procStatus = ProcessStatus_Undefined;
     752        int procRc = VINF_SUCCESS;
     753
     754        switch (dataCb.uStatus)
     755        {
     756            case PROC_STS_STARTED:
     757            {
     758                procStatus = ProcessStatus_Started;
     759                mData.mPID = dataCb.uPID; /* Set the process PID. */
     760                break;
     761            }
     762
     763            case PROC_STS_TEN:
     764            {
     765                procStatus = ProcessStatus_TerminatedNormally;
     766                mData.mExitCode = dataCb.uFlags; /* Contains the exit code. */
     767                break;
     768            }
     769
     770            case PROC_STS_TES:
     771            {
     772                procStatus = ProcessStatus_TerminatedSignal;
     773                mData.mExitCode = dataCb.uFlags; /* Contains the signal. */
     774                break;
     775            }
     776
     777            case PROC_STS_TEA:
     778            {
     779                procStatus = ProcessStatus_TerminatedAbnormally;
     780                break;
     781            }
     782
     783            case PROC_STS_TOK:
     784            {
     785                procStatus = ProcessStatus_TimedOutKilled;
     786                break;
     787            }
     788
     789            case PROC_STS_TOA:
     790            {
     791                procStatus = ProcessStatus_TimedOutAbnormally;
     792                break;
     793            }
     794
     795            case PROC_STS_DWN:
     796            {
     797                procStatus = ProcessStatus_Down;
     798                break;
     799            }
     800
     801            case PROC_STS_ERROR:
     802            {
     803                procRc = dataCb.uFlags; /* mFlags contains the IPRT error sent from the guest. */
     804                procStatus = ProcessStatus_Error;
     805                break;
     806            }
     807
     808            case PROC_STS_UNDEFINED:
     809            default:
     810            {
     811                /* Silently skip this request. */
     812                procStatus = ProcessStatus_Undefined;
     813                break;
     814            }
     815        }
     816
     817        LogFlowThisFunc(("Got rc=%Rrc, procSts=%ld, procRc=%Rrc\n",
     818                         vrc, procStatus, procRc));
     819
     820        /* Set the process status. */
     821        int rc2 = setProcessStatus(procStatus, procRc);
     822        if (RT_SUCCESS(vrc))
     823            vrc = rc2;
     824    }
    807825
    808826    LogFlowFuncLeaveRC(vrc);
     
    832850
    833851    vrc = checkPID(dataCb.uPID);
    834     AssertRCReturn(vrc, vrc);
    835 
    836     com::SafeArray<BYTE> data((size_t)dataCb.cbData);
    837     if (dataCb.cbData)
    838         data.initFrom((BYTE*)dataCb.pvData, dataCb.cbData);
    839 
    840     fireGuestProcessOutputEvent(mEventSource, mSession, this,
    841                                 mData.mPID, dataCb.uHandle, dataCb.cbData, ComSafeArrayAsInParam(data));
     852    if (RT_SUCCESS(vrc))
     853    {
     854        com::SafeArray<BYTE> data((size_t)dataCb.cbData);
     855        if (dataCb.cbData)
     856            data.initFrom((BYTE*)dataCb.pvData, dataCb.cbData);
     857
     858        fireGuestProcessOutputEvent(mEventSource, mSession, this,
     859                                    mData.mPID, dataCb.uHandle, dataCb.cbData, ComSafeArrayAsInParam(data));
     860    }
    842861
    843862    LogFlowFuncLeaveRC(vrc);
     
    880899    try
    881900    {
    882         eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
     901        /*
     902         * On Guest Additions < 4.3 there is no guarantee that the process status
     903         * change arrives *after* the output event, e.g. if this was the last output
     904         * block being read and the process will report status "terminate".
     905         * So just skip checking for process status change and only wait for the
     906         * output event.
     907         */
     908        if (mSession->getProtocolVersion() >= 2)
     909            eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
    883910        eventTypes.push_back(VBoxEventType_OnGuestProcessOutput);
    884911
    885         vrc = registerEvent(eventTypes, &pEvent);
     912        vrc = registerWaitEvent(eventTypes, &pEvent);
    886913    }
    887914    catch (std::bad_alloc)
     
    911938                            pvData, cbData, pcbRead);
    912939
    913     unregisterEvent(pEvent);
     940    unregisterWaitEvent(pEvent);
    914941
    915942    LogFlowFuncLeaveRC(vrc);
     
    933960        AssertMsg(RT_SUCCESS(procRc), ("Guest rc must not be an error (%Rrc)\n", procRc));
    934961
    935     if (mData.mStatus != procStatus)
     962    if (mData.mStatus != procStatus) /* Was there a process status change? */
    936963    {
    937964        mData.mStatus = procStatus;
     
    965992}
    966993
    967 int GuestProcess::startProcess(int *pGuestRc)
    968 {
    969     LogFlowThisFunc(("aCmd=%s, aTimeoutMS=%RU32, fFlags=%x\n",
    970                      mData.mProcess.mCommand.c_str(), mData.mProcess.mTimeoutMS, mData.mProcess.mFlags));
     994int GuestProcess::startProcess(uint32_t uTimeoutMS, int *pGuestRc)
     995{
     996    LogFlowThisFunc(("uTimeoutMS=%RU32, procCmd=%s, procTimeoutMS=%RU32, procFlags=%x\n",
     997                     uTimeoutMS, mData.mProcess.mCommand.c_str(), mData.mProcess.mTimeoutMS, mData.mProcess.mFlags));
    971998
    972999    /* Wait until the caller function (if kicked off by a thread)
     
    9841011        eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
    9851012
    986         vrc = registerEvent(eventTypes, &pEvent);
     1013        vrc = registerWaitEvent(eventTypes, &pEvent);
    9871014    }
    9881015    catch (std::bad_alloc)
     
    10411068    if (RT_SUCCESS(vrc))
    10421069        vrc = mData.mProcess.mEnvironment.BuildEnvironmentBlock(&pvEnv, &cbEnv, NULL /* cEnv */);
    1043 
    1044     uint32_t uTimeoutMS = mData.mProcess.mTimeoutMS;
    10451070
    10461071    if (RT_SUCCESS(vrc))
     
    10781103            paParms[i++].setUInt32(UINT32_MAX /* Infinite timeout */);
    10791104        else
    1080             paParms[i++].setUInt32(uTimeoutMS);
     1105            paParms[i++].setUInt32(mData.mProcess.mTimeoutMS);
    10811106        if (uProtocol >= 2)
    10821107        {
     
    11041129
    11051130    if (RT_SUCCESS(vrc))
    1106         vrc = waitForStatusChange(pEvent, ProcessWaitForFlag_Start, uTimeoutMS,
     1131        vrc = waitForStatusChange(pEvent, uTimeoutMS,
    11071132                                  NULL /* Process status */, pGuestRc);
    1108     unregisterEvent(pEvent);
     1133    unregisterWaitEvent(pEvent);
    11091134
    11101135    LogFlowFuncLeaveRC(vrc);
     
    11581183    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    11591184
    1160     int vrc = pProcess->startProcess(NULL /* Guest rc, ignored */);
     1185    int vrc = pProcess->startProcess(30 * 1000 /* 30s timeout */,
     1186                                     NULL /* Guest rc, ignored */);
    11611187    /* Nothing to do here anymore. */
    11621188
     
    11651191}
    11661192
    1167 int GuestProcess::terminateProcess(int *pGuestRc)
    1168 {
    1169     LogFlowThisFuncEnter();
     1193int GuestProcess::terminateProcess(uint32_t uTimeoutMS, int *pGuestRc)
     1194{
     1195    /* pGuestRc is optional. */
     1196    LogFlowThisFunc(("uTimeoutMS=%RU32\n", uTimeoutMS));
    11701197
    11711198    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    11721199
     1200    if (mData.mStatus != ProcessStatus_Started)
     1201    {
     1202        LogFlowThisFunc(("Process not started (yet), nothing to terminate\n"));
     1203        return VINF_SUCCESS; /* Nothing to do (anymore). */
     1204    }
     1205
     1206    int vrc = VINF_SUCCESS;
     1207
    11731208    AssertPtr(mSession);
    1174     if (mSession->getProtocolVersion() < 99)
    1175         return VERR_NOT_SUPPORTED;
    1176 
    1177     if (mData.mStatus != ProcessStatus_Started)
    1178         return VINF_SUCCESS; /* Nothing to do (anymore). */
    1179 
    1180     int vrc;
    1181 
    1182     GuestWaitEvent *pEvent = NULL;
    1183     std::list < VBoxEventType_T > eventTypes;
    1184     try
    1185     {
    1186         eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
    1187 
    1188         vrc = registerEvent(eventTypes, &pEvent);
    1189     }
    1190     catch (std::bad_alloc)
    1191     {
    1192         vrc = VERR_NO_MEMORY;
    1193     }
    1194 
    1195     if (RT_FAILURE(vrc))
    1196         return vrc;
    1197 
    1198     VBOXHGCMSVCPARM paParms[4];
    1199     int i = 0;
    1200     paParms[i++].setUInt32(pEvent->ContextID());
    1201     paParms[i++].setUInt32(mData.mPID);
    1202 
    1203     alock.release(); /* Drop the write lock before sending. */
    1204 
    1205     vrc = sendCommand(HOST_EXEC_TERMINATE, i, paParms);
     1209    /* Note: VBox < 4.3 (aka protocol version 1) does not
     1210     *       support this, so just skip. */
     1211    if (mSession->getProtocolVersion() < 2)
     1212        vrc = VERR_NOT_SUPPORTED;
     1213
    12061214    if (RT_SUCCESS(vrc))
    1207         vrc = waitForStatusChange(pEvent, ProcessWaitForFlag_Terminate,
    1208                                   30 * 1000 /* 30s timeout */,
    1209                                   NULL /* ProcessStatus */, pGuestRc);
    1210     unregisterEvent(pEvent);
     1215    {
     1216        GuestWaitEvent *pEvent = NULL;
     1217        std::list < VBoxEventType_T > eventTypes;
     1218        try
     1219        {
     1220            eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
     1221
     1222            vrc = registerWaitEvent(eventTypes, &pEvent);
     1223        }
     1224        catch (std::bad_alloc)
     1225        {
     1226            vrc = VERR_NO_MEMORY;
     1227        }
     1228
     1229        if (RT_FAILURE(vrc))
     1230            return vrc;
     1231
     1232        VBOXHGCMSVCPARM paParms[4];
     1233        int i = 0;
     1234        paParms[i++].setUInt32(pEvent->ContextID());
     1235        paParms[i++].setUInt32(mData.mPID);
     1236
     1237        alock.release(); /* Drop the write lock before sending. */
     1238
     1239        vrc = sendCommand(HOST_EXEC_TERMINATE, i, paParms);
     1240        if (RT_SUCCESS(vrc))
     1241            vrc = waitForStatusChange(pEvent, uTimeoutMS,
     1242                                      NULL /* ProcessStatus */, pGuestRc);
     1243        unregisterWaitEvent(pEvent);
     1244    }
    12111245
    12121246    LogFlowFuncLeaveRC(vrc);
     
    12141248}
    12151249
    1216 int GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc)
    1217 {
    1218     LogFlowThisFuncEnter();
    1219 
    1220     AssertReturn(fWaitFlags, VERR_INVALID_PARAMETER);
    1221 
    1222     /*LogFlowThisFunc(("fWaitFlags=0x%x, uTimeoutMS=%RU32, mStatus=%RU32, mWaitCount=%RU32, mWaitEvent=%p, pGuestRc=%p\n",
    1223                      fWaitFlags, uTimeoutMS, mData.mStatus, mData.mWaitCount, mData.mWaitEvent, pGuestRc));*/
    1224 
    1225     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    1226 
    1227     /* Did some error occur before? Then skip waiting and return. */
    1228     if (mData.mStatus == ProcessStatus_Error)
    1229     {
    1230         waitResult = ProcessWaitResult_Error;
    1231         AssertMsg(RT_FAILURE(mData.mRC), ("No error rc (%Rrc) set when guest process indicated an error\n", mData.mRC));
    1232         if (pGuestRc)
    1233             *pGuestRc = mData.mRC; /* Return last set error. */
    1234         return VERR_GSTCTL_GUEST_ERROR;
    1235     }
    1236 
    1237     waitResult = ProcessWaitResult_None;
     1250/* static */
     1251ProcessWaitResult_T GuestProcess::waitFlagsToResultEx(uint32_t fWaitFlags,
     1252                                                      ProcessStatus_T procStatus, uint32_t uProcFlags,
     1253                                                      uint32_t uProtocol)
     1254{
     1255    ProcessWaitResult_T waitResult = ProcessWaitResult_None;
     1256
    12381257    if (   (fWaitFlags & ProcessWaitForFlag_Terminate)
    12391258        || (fWaitFlags & ProcessWaitForFlag_StdIn)
     
    12411260        || (fWaitFlags & ProcessWaitForFlag_StdErr))
    12421261    {
    1243         switch (mData.mStatus)
     1262        switch (procStatus)
    12441263        {
    12451264            case ProcessStatus_TerminatedNormally:
     
    12661285                 * anything here anymore and return.
    12671286                 */
    1268                 if (mData.mProcess.mFlags & ProcessCreateFlag_WaitForProcessStartOnly)
     1287                if (uProcFlags & ProcessCreateFlag_WaitForProcessStartOnly)
    12691288                    waitResult = ProcessWaitResult_Start;
    12701289                break;
     
    12731292            case ProcessStatus_Undefined:
    12741293            case ProcessStatus_Starting:
    1275                 /* Do the waiting below. */
     1294                /* No result available yet. */
    12761295                break;
    12771296
    12781297            default:
    1279                 AssertMsgFailed(("Unhandled process status %ld\n", mData.mStatus));
    1280                 return VERR_NOT_IMPLEMENTED;
     1298                AssertMsgFailed(("Unhandled process status %ld\n", procStatus));
     1299                break;
    12811300        }
    12821301    }
    12831302    else if (fWaitFlags & ProcessWaitForFlag_Start)
    12841303    {
    1285         switch (mData.mStatus)
     1304        switch (procStatus)
    12861305        {
    12871306            case ProcessStatus_Started:
     
    13061325            case ProcessStatus_Undefined:
    13071326            case ProcessStatus_Starting:
    1308                 /* Do the waiting below. */
     1327                /* No result available yet. */
    13091328                break;
    13101329
    13111330            default:
    1312                 AssertMsgFailed(("Unhandled process status %ld\n", mData.mStatus));
    1313                 return VERR_NOT_IMPLEMENTED;
     1331                AssertMsgFailed(("Unhandled process status %ld\n", procStatus));
     1332                break;
    13141333        }
    13151334    }
     
    13201339     ** @todo ProcessWaitForFlag_Std* flags are not implemented yet.
    13211340     */
    1322     if (mSession->getProtocolVersion() < 99)
     1341    if (uProtocol < 99) /* See @todo above. */
    13231342    {
    13241343        if (   waitResult == ProcessWaitResult_None
     
    13361355    }
    13371356
     1357    return waitResult;
     1358}
     1359
     1360ProcessWaitResult_T GuestProcess::waitFlagsToResult(uint32_t fWaitFlags)
     1361{
     1362    AssertPtr(mSession);
     1363    return GuestProcess::waitFlagsToResultEx(fWaitFlags, mData.mStatus, mData.mProcess.mFlags,
     1364                                             mSession->getProtocolVersion());
     1365}
     1366
     1367int GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc)
     1368{
     1369    LogFlowThisFuncEnter();
     1370
     1371    AssertReturn(fWaitFlags, VERR_INVALID_PARAMETER);
     1372
     1373    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1374
     1375    LogFlowThisFunc(("fWaitFlags=0x%x, uTimeoutMS=%RU32, mStatus=%RU32, pGuestRc=%p\n",
     1376                     fWaitFlags, uTimeoutMS, mData.mStatus, pGuestRc));
     1377
     1378    /* Did some error occur before? Then skip waiting and return. */
     1379    if (mData.mStatus == ProcessStatus_Error)
     1380    {
     1381        waitResult = ProcessWaitResult_Error;
     1382        AssertMsg(RT_FAILURE(mData.mRC), ("No error rc (%Rrc) set when guest process indicated an error\n", mData.mRC));
     1383        if (pGuestRc)
     1384            *pGuestRc = mData.mRC; /* Return last set error. */
     1385        return VERR_GSTCTL_GUEST_ERROR;
     1386    }
     1387
     1388    waitResult = waitFlagsToResult(fWaitFlags);
    13381389    LogFlowThisFunc(("procStatus=%ld, procRc=%Rrc, waitResult=%ld\n",
    13391390                     mData.mStatus, mData.mRC, waitResult));
     
    13571408        eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
    13581409
    1359         vrc = registerEvent(eventTypes, &pEvent);
     1410        vrc = registerWaitEvent(eventTypes, &pEvent);
    13601411    }
    13611412    catch (std::bad_alloc)
     
    13671418        return vrc;
    13681419
    1369     ProcessStatus_T processStatus;
    1370     vrc = waitForStatusChange(pEvent, fWaitFlags,
    1371                               uTimeoutMS, &processStatus, pGuestRc);
    1372     if (RT_SUCCESS(vrc))
    1373     {
    1374         switch (processStatus)
    1375         {
    1376             case ProcessStatus_Started:
    1377                 waitResult = ProcessWaitResult_Start;
    1378                 break;
    1379 
    1380             case ProcessStatus_TerminatedNormally:
    1381             case ProcessStatus_TerminatedAbnormally:
    1382             case ProcessStatus_TerminatedSignal:
    1383                 waitResult = ProcessWaitResult_Terminate;
    1384                 break;
    1385 
    1386             case ProcessStatus_TimedOutKilled:
    1387             case ProcessStatus_TimedOutAbnormally:
    1388                 waitResult = ProcessWaitResult_Timeout;
    1389                 break;
    1390 
    1391             case ProcessStatus_Down:
    1392                 waitResult = ProcessWaitResult_Terminate;
    1393                 break;
    1394 
    1395             case ProcessStatus_Error:
    1396                 waitResult = ProcessWaitResult_Error;
    1397                 break;
    1398 
    1399             default:
    1400                 waitResult = ProcessWaitResult_Status;
    1401                 break;
    1402         }
    1403     }
    1404 
    1405     unregisterEvent(pEvent);
    1406 
    1407     LogFlowFuncLeaveRC(vrc);
     1420    /*
     1421     * Do the actual waiting.
     1422     */
     1423    ProcessStatus_T processStatus = ProcessStatus_Undefined;
     1424    uint64_t u64StartMS = RTTimeMilliTS();
     1425    for (;;)
     1426    {
     1427        uint64_t u32ElapsedMS = RTTimeMilliTS() - u64StartMS;
     1428        if (   uTimeoutMS   != RT_INDEFINITE_WAIT
     1429            && u32ElapsedMS >= uTimeoutMS)
     1430        {
     1431            vrc = VERR_TIMEOUT;
     1432            break;
     1433        }
     1434
     1435        vrc = waitForStatusChange(pEvent,
     1436                                    uTimeoutMS == RT_INDEFINITE_WAIT
     1437                                  ? RT_INDEFINITE_WAIT : uTimeoutMS - u32ElapsedMS,
     1438                                  &processStatus, pGuestRc);
     1439        if (RT_SUCCESS(vrc))
     1440        {
     1441            AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     1442
     1443            waitResult = waitFlagsToResultEx(fWaitFlags, processStatus,
     1444                                             mData.mProcess.mFlags, mSession->getProtocolVersion());
     1445            LogFlowThisFunc(("Got new status change: waitResult=%ld, processStatus=%ld\n",
     1446                             waitResult, processStatus));
     1447            if (ProcessWaitResult_None != waitResult) /* We got a waiting result. */
     1448                break;
     1449        }
     1450        else /* Waiting failed, bail out. */
     1451            break;
     1452    }
     1453
     1454    unregisterWaitEvent(pEvent);
     1455
     1456    LogFlowThisFunc(("waitResult=%ld, processStatus=%ld, rc=%Rrc\n",
     1457                     waitResult, processStatus, vrc));
    14081458    return vrc;
    14091459}
     
    14401490    }
    14411491
    1442     LogFlowFuncLeaveRC(vrc);
     1492    LogFlowThisFunc(("Returning pEvent=%p, uHandle=%RU32, rc=%Rrc\n",
     1493                     pEvent, uHandle, vrc));
    14431494    return vrc;
    14441495}
     
    15061557}
    15071558
    1508 int GuestProcess::waitForStatusChange(GuestWaitEvent *pEvent, uint32_t fWaitFlags, uint32_t uTimeoutMS,
     1559int GuestProcess::waitForStatusChange(GuestWaitEvent *pEvent, uint32_t uTimeoutMS,
    15091560                                      ProcessStatus_T *pProcessStatus, int *pGuestRc)
    15101561{
    15111562    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
     1563    /* pProcessStatus is optional. */
     1564    /* pGuestRc is optional. */
    15121565
    15131566    VBoxEventType_T evtType;
     
    15351588        hr = errorInfo->COMGETTER(ResultDetail)(&lGuestRc);
    15361589        ComAssertComRC(hr);
     1590
     1591        LogFlowThisFunc(("resultDetail=%RI32 (rc=%Rrc)\n",
     1592                         lGuestRc, lGuestRc));
     1593
    15371594        if (RT_FAILURE((int)lGuestRc))
    15381595            vrc = VERR_GSTCTL_GUEST_ERROR;
     
    15421599    }
    15431600
    1544     LogFlowFuncLeaveRC(vrc);
     1601    LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
    15451602    return vrc;
     1603}
     1604
     1605/* static */
     1606bool GuestProcess::waitResultImpliesEx(ProcessWaitResult_T waitResult,
     1607                                       ProcessStatus_T procStatus, uint32_t uProcFlags,
     1608                                       uint32_t uProtocol)
     1609{
     1610    bool fImplies;
     1611
     1612    switch (waitResult)
     1613    {
     1614        case ProcessWaitResult_Start:
     1615            fImplies = procStatus == ProcessStatus_Started;
     1616            break;
     1617
     1618        case ProcessWaitResult_Terminate:
     1619            fImplies = (   procStatus == ProcessStatus_TerminatedNormally
     1620                        || procStatus == ProcessStatus_TerminatedSignal
     1621                        || procStatus == ProcessStatus_TerminatedAbnormally
     1622                        || procStatus == ProcessStatus_TimedOutKilled
     1623                        || procStatus == ProcessStatus_TimedOutAbnormally
     1624                        || procStatus == ProcessStatus_Down
     1625                        || procStatus == ProcessStatus_Error);
     1626            break;
     1627
     1628        default:
     1629            fImplies = false;
     1630            break;
     1631    }
     1632
     1633    return fImplies;
    15461634}
    15471635
     
    15701658    try
    15711659    {
    1572         eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
     1660        /*
     1661         * On Guest Additions < 4.3 there is no guarantee that the process status
     1662         * change arrives *after* the input event, e.g. if this was the last input
     1663         * block being written and the process will report status "terminate".
     1664         * So just skip checking for process status change and only wait for the
     1665         * input event.
     1666         */
     1667        if (mSession->getProtocolVersion() >= 2)
     1668            eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
    15731669        eventTypes.push_back(VBoxEventType_OnGuestProcessInputNotify);
    15741670
    1575         vrc = registerEvent(eventTypes, &pEvent);
     1671        vrc = registerWaitEvent(eventTypes, &pEvent);
    15761672    }
    15771673    catch (std::bad_alloc)
     
    15931689    alock.release(); /* Drop the write lock before sending. */
    15941690
     1691    uint32_t cbProcessed = 0;
    15951692    vrc = sendCommand(HOST_EXEC_SET_INPUT, i, paParms);
    15961693    if (RT_SUCCESS(vrc))
    15971694    {
    15981695        ProcessInputStatus_T inputStatus;
    1599         uint32_t cbProcessed;
    1600         vrc = waitForInputNotify(pEvent, uHandle, uTimeoutMS, &inputStatus, &cbProcessed);
     1696        vrc = waitForInputNotify(pEvent, uHandle, uTimeoutMS,
     1697                                &inputStatus, &cbProcessed);
    16011698        if (RT_SUCCESS(vrc))
    16021699        {
     
    16091706    }
    16101707
    1611     unregisterEvent(pEvent);
    1612 
    1613     LogFlowFuncLeaveRC(vrc);
     1708    unregisterWaitEvent(pEvent);
     1709
     1710    LogFlowThisFunc(("Returning cbProcessed=%RU32, rc=%Rrc\n",
     1711                     cbProcessed, vrc));
    16141712    return vrc;
    16151713}
     
    16791777
    16801778    int guestRc;
    1681     int vrc = terminateProcess(&guestRc);
     1779    int vrc = terminateProcess(30 * 1000 /* Timeout in ms */,
     1780                               &guestRc);
    16821781    if (RT_FAILURE(vrc))
    16831782    {
     
    17021801    }
    17031802
     1803    /* Remove the process from our internal session list. Only an API client
     1804     * now may hold references to it. */
    17041805    AssertPtr(mSession);
    17051806    mSession->processRemoveFromList(this);
    17061807
    1707     /*
    1708      * Release autocaller before calling uninit.
    1709      */
    1710     autoCaller.release();
    1711 
    1712     uninit();
    1713 
    1714     LogFlowFuncLeaveRC(vrc);
     1808    LogFlowThisFunc(("Returning rc=%Rrc\n", vrc));
    17151809    return hr;
    17161810#endif /* VBOX_WITH_GUEST_CONTROL */
     
    18671961GuestProcessTool::~GuestProcessTool(void)
    18681962{
    1869     Terminate();
     1963    Terminate(30 * 1000, NULL /* pGuestRc */);
    18701964}
    18711965
     
    18861980    int vrc = pSession->processCreateExInteral(mStartupInfo, pProcess);
    18871981    if (RT_SUCCESS(vrc))
    1888         vrc = fAsync ? pProcess->startProcessAsync() : pProcess->startProcess(pGuestRc);
     1982        vrc = fAsync ? pProcess->startProcessAsync() : pProcess->startProcess(30 * 1000 /* 30s timeout */,
     1983                                                                              pGuestRc);
    18891984
    18901985    if (   RT_SUCCESS(vrc)
     
    19982093        fWaitFlags |= ProcessWaitForFlag_StdErr;
    19992094
    2000     LogFlowFunc(("waitFlags=0x%x\n", fWaitFlags));
     2095    LogFlowThisFunc(("waitFlags=0x%x\n", fWaitFlags));
    20012096
    20022097    /** @todo Decrease timeout. */
     
    21202215}
    21212216
    2122 void GuestProcessTool::Terminate(void)
     2217int GuestProcessTool::Terminate(uint32_t uTimeoutMS, int *pGuestRc)
    21232218{
    21242219    LogFlowThisFuncEnter();
    21252220
     2221    int rc = VINF_SUCCESS;
    21262222    if (!pProcess.isNull())
    21272223    {
    2128         /** @todo Add pProcess.Terminate() here as soon as it's implemented. */
     2224        rc = pProcess->terminateProcess(uTimeoutMS, pGuestRc);
    21292225
    21302226        Assert(pSession);
     
    21342230        pProcess.setNull();
    21352231    }
    2136 
    2137     LogFlowThisFuncLeave();
    2138 }
    2139 
     2232    else
     2233        rc = VERR_NOT_FOUND;
     2234
     2235    LogFlowFuncLeaveRC(rc);
     2236    return rc;
     2237}
     2238
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r45805 r47469  
    207207    if (RT_SUCCESS(rc))
    208208    {
    209         unconst(mEventSource).createObject();
    210         Assert(!mEventSource.isNull());
    211         hr = mEventSource->init(static_cast<IGuestSession*>(this));
     209        hr = unconst(mEventSource).createObject();
    212210        if (FAILED(hr))
    213             rc = VERR_COM_UNEXPECTED;
     211            rc = VERR_NO_MEMORY;
     212        else
     213        {
     214            hr = mEventSource->init(static_cast<IGuestSession*>(this));
     215            if (FAILED(hr))
     216                rc = VERR_COM_UNEXPECTED;
     217        }
    214218    }
    215219
     
    226230            if (SUCCEEDED(hr))
    227231            {
    228                 mListener = thisListener;
    229 
    230232                com::SafeArray <VBoxEventType_T> eventTypes;
    231233                eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged);
    232                 hr = mEventSource->RegisterListener(mListener,
     234                hr = mEventSource->RegisterListener(thisListener,
    233235                                                    ComSafeArrayAsInParam(eventTypes),
    234236                                                    TRUE /* Active listener */);
    235237                if (SUCCEEDED(hr))
    236238                {
     239                    mLocalListener = thisListener;
     240
    237241                    rc = RTCritSectInit(&mWaitEventCritSect);
    238242                    AssertRC(rc);
     
    258262        autoInitSpan.setFailed();
    259263
    260     LogFlowFuncLeaveRC(rc);
     264    LogFlowThisFunc(("mName=%s, mID=%RU32, mIsInternal=%RTbool, rc=%Rrc\n",
     265                     mData.mSession.mName.c_str(), mData.mSession.mID, mData.mSession.mIsInternal, rc));
    261266    return rc;
    262267#endif /* VBOX_WITH_GUEST_CONTROL */
     
    284289         itDirs != mData.mDirectories.end(); ++itDirs)
    285290    {
    286         (*itDirs)->uninit();
     291        (*itDirs)->Release();
    287292    }
    288293    mData.mDirectories.clear();
     
    293298         itFiles != mData.mFiles.end(); ++itFiles)
    294299    {
    295         itFiles->second->uninit();
     300        itFiles->second->Release();
    296301    }
    297302    mData.mFiles.clear();
     
    302307         itProcs != mData.mProcesses.end(); ++itProcs)
    303308    {
    304         itProcs->second->uninit();
     309        itProcs->second->Release();
    305310    }
    306311    mData.mProcesses.clear();
     
    308313    LogFlowThisFunc(("mNumObjects=%RU32\n", mData.mNumObjects));
    309314
     315    baseUninit();
     316
     317    mEventSource->UnregisterListener(mLocalListener);
    310318    unconst(mEventSource).setNull();
    311     unregisterEventListener();
    312319
    313320#endif /* VBOX_WITH_GUEST_CONTROL */
     
    457464
    458465    mData.mTimeout = aTimeout;
     466
     467    LogFlowFuncLeaveRC(S_OK);
     468    return S_OK;
     469#endif /* VBOX_WITH_GUEST_CONTROL */
     470}
     471
     472STDMETHODIMP GuestSession::COMGETTER(ProtocolVersion)(ULONG *aVersion)
     473{
     474#ifndef VBOX_WITH_GUEST_CONTROL
     475    ReturnComNotImplemented();
     476#else
     477    LogFlowThisFuncEnter();
     478
     479    CheckComArgOutPointerValid(aVersion);
     480
     481    AutoCaller autoCaller(this);
     482    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     483
     484    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     485
     486    *aVersion = mData.mProtocolVersion;
    459487
    460488    LogFlowFuncLeaveRC(S_OK);
     
    539567    collection.detachTo(ComSafeArrayOutArg(aProcesses));
    540568
     569    LogFlowFunc(("mProcesses=%zu\n", collection.size()));
     570    return S_OK;
     571#endif /* VBOX_WITH_GUEST_CONTROL */
     572}
     573
     574STDMETHODIMP GuestSession::COMGETTER(Directories)(ComSafeArrayOut(IGuestDirectory *, aDirectories))
     575{
     576#ifndef VBOX_WITH_GUEST_CONTROL
     577    ReturnComNotImplemented();
     578#else
     579    LogFlowThisFuncEnter();
     580
     581    CheckComArgOutSafeArrayPointerValid(aDirectories);
     582
     583    AutoCaller autoCaller(this);
     584    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     585
     586    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     587
     588    SafeIfaceArray<IGuestDirectory> collection(mData.mDirectories);
     589    collection.detachTo(ComSafeArrayOutArg(aDirectories));
     590
     591    LogFlowFunc(("mDirectories=%zu\n", collection.size()));
     592    return S_OK;
     593#endif /* VBOX_WITH_GUEST_CONTROL */
     594}
     595
     596STDMETHODIMP GuestSession::COMGETTER(Files)(ComSafeArrayOut(IGuestFile *, aFiles))
     597{
     598#ifndef VBOX_WITH_GUEST_CONTROL
     599    ReturnComNotImplemented();
     600#else
     601    LogFlowThisFuncEnter();
     602
     603    CheckComArgOutSafeArrayPointerValid(aFiles);
     604
     605    AutoCaller autoCaller(this);
     606    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     607
     608    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     609
     610    SafeIfaceArray<IGuestFile> collection(mData.mFiles);
     611    collection.detachTo(ComSafeArrayOutArg(aFiles));
     612
     613    LogFlowFunc(("mFiles=%zu\n", collection.size()));
     614    return S_OK;
     615#endif /* VBOX_WITH_GUEST_CONTROL */
     616}
     617
     618STDMETHODIMP GuestSession::COMGETTER(EventSource)(IEventSource ** aEventSource)
     619{
     620#ifndef VBOX_WITH_GUEST_CONTROL
     621    ReturnComNotImplemented();
     622#else
     623    LogFlowThisFuncEnter();
     624
     625    CheckComArgOutPointerValid(aEventSource);
     626
     627    AutoCaller autoCaller(this);
     628    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     629
     630    // no need to lock - lifetime constant
     631    mEventSource.queryInterfaceTo(aEventSource);
     632
    541633    LogFlowFuncLeaveRC(S_OK);
    542634    return S_OK;
     
    544636}
    545637
    546 STDMETHODIMP GuestSession::COMGETTER(Directories)(ComSafeArrayOut(IGuestDirectory *, aDirectories))
    547 {
    548 #ifndef VBOX_WITH_GUEST_CONTROL
    549     ReturnComNotImplemented();
    550 #else
    551     LogFlowThisFuncEnter();
    552 
    553     CheckComArgOutSafeArrayPointerValid(aDirectories);
    554 
    555     AutoCaller autoCaller(this);
    556     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    557 
    558     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    559 
    560     SafeIfaceArray<IGuestDirectory> collection(mData.mDirectories);
    561     collection.detachTo(ComSafeArrayOutArg(aDirectories));
    562 
    563     LogFlowFuncLeaveRC(S_OK);
    564     return S_OK;
    565 #endif /* VBOX_WITH_GUEST_CONTROL */
    566 }
    567 
    568 STDMETHODIMP GuestSession::COMGETTER(Files)(ComSafeArrayOut(IGuestFile *, aFiles))
    569 {
    570 #ifndef VBOX_WITH_GUEST_CONTROL
    571     ReturnComNotImplemented();
    572 #else
    573     LogFlowThisFuncEnter();
    574 
    575     CheckComArgOutSafeArrayPointerValid(aFiles);
    576 
    577     AutoCaller autoCaller(this);
    578     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    579 
    580     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    581 
    582     SafeIfaceArray<IGuestFile> collection(mData.mFiles);
    583     collection.detachTo(ComSafeArrayOutArg(aFiles));
    584 
    585     LogFlowFuncLeaveRC(S_OK);
    586     return S_OK;
    587 #endif /* VBOX_WITH_GUEST_CONTROL */
    588 }
    589 
    590 STDMETHODIMP GuestSession::COMGETTER(EventSource)(IEventSource ** aEventSource)
    591 {
    592 #ifndef VBOX_WITH_GUEST_CONTROL
    593     ReturnComNotImplemented();
    594 #else
    595     LogFlowThisFuncEnter();
    596 
    597     CheckComArgOutPointerValid(aEventSource);
    598 
    599     AutoCaller autoCaller(this);
    600     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    601 
    602     // no need to lock - lifetime constant
    603     mEventSource.queryInterfaceTo(aEventSource);
    604 
    605     LogFlowFuncLeaveRC(S_OK);
    606     return S_OK;
    607 #endif /* VBOX_WITH_GUEST_CONTROL */
    608 }
    609 
    610638// private methods
    611639///////////////////////////////////////////////////////////////////////////////
     
    617645    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    618646
    619     /* Legacy Guest Additions don't support opening dedicated
    620        guest sessions. */
     647    /* Guest Additions < 4.3 don't support closing dedicated
     648       guest sessions, skip. */
    621649    if (mData.mProtocolVersion < 2)
    622650    {
     
    638666        eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged);
    639667
    640         vrc = registerEvent(mData.mSession.mID, 0 /* Object ID */,
    641                             eventTypes, &pEvent);
     668        vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */,
     669                                eventTypes, &pEvent);
    642670    }
    643671    catch (std::bad_alloc)
     
    666694    }
    667695
    668     unregisterEvent(pEvent);
     696    unregisterWaitEvent(pEvent);
    669697
    670698    LogFlowFuncLeaveRC(vrc);
     
    13191347}
    13201348
    1321 int GuestSession::startSessionIntenal(int *pGuestRc)
     1349int GuestSession::startSessionInternal(int *pGuestRc)
    13221350{
    13231351    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     
    13271355                     mData.mSession.mOpenFlags, mData.mSession.mOpenTimeoutMS));
    13281356
    1329     /* Legacy Guest Additions don't support opening dedicated
     1357    /* Guest Additions < 4.3 don't support opening dedicated
    13301358       guest sessions. Simply return success here. */
    13311359    if (mData.mProtocolVersion < 2)
     
    13531381        eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged);
    13541382
    1355         vrc = registerEvent(mData.mSession.mID, 0 /* Object ID */,
    1356                             eventTypes, &pEvent);
     1383        vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */,
     1384                                eventTypes, &pEvent);
    13571385    }
    13581386    catch (std::bad_alloc)
     
    13871415    }
    13881416
    1389     unregisterEvent(pEvent);
     1417    unregisterWaitEvent(pEvent);
    13901418
    13911419    LogFlowFuncLeaveRC(vrc);
     
    14391467    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    14401468
    1441     int vrc = pSession->startSessionIntenal(NULL /* Guest rc, ignored */);
     1469    int vrc = pSession->startSessionInternal(NULL /* Guest rc, ignored */);
    14421470    /* Nothing to do here anymore. */
    14431471
     
    14761504            LogFlowFunc(("Removing process ID=%RU32 (Session: %RU32), guest PID=%RU32 (now total %ld processes, %ld objects)\n",
    14771505                         pCurProc->getObjectID(), mData.mSession.mID, uPID, mData.mProcesses.size() - 1, mData.mNumObjects - 1));
     1506
     1507            pCurProc->cancelWaitEvents();
     1508
     1509            itProcs->second->Release();
    14781510
    14791511            mData.mProcesses.erase(itProcs);
     
    17721804int GuestSession::queryInfo(void)
    17731805{
    1774 #ifndef DEBUG_andy
    1775     /* Since the new functions are not fully implemented yet, force Main
    1776        to use protocol ver 1 so far. */
    1777     mData.mProtocolVersion = 1;
    1778 #else
    1779  #if 1
    1780     /* For debugging only: Hardcode version. */
    1781     mData.mProtocolVersion = 2;
    1782  #else
    17831806    /*
    17841807     * Try querying the guest control protocol version running on the guest.
     
    17891812
    17901813    uint32_t uVerAdditions = pGuest->getAdditionsVersion();
    1791     mData.mProtocolVersion = (   VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions) >= 4
    1792                               && VBOX_FULL_VERSION_GET_MINOR(uVerAdditions) >= 3) /** @todo What's about v5.0 ? */
     1814    uint32_t uVBoxMajor    = VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions);
     1815    uint32_t uVBoxMinor    = VBOX_FULL_VERSION_GET_MINOR(uVerAdditions);
     1816
     1817    mData.mProtocolVersion = (
     1818                              /* VBox 5.0 and up. */
     1819                                 uVBoxMajor  >= 5
     1820                              /* VBox 4.3 and up. */
     1821                              || (uVBoxMajor == 4 && uVBoxMinor >= 3))
    17931822                           ? 2  /* Guest control 2.0. */
    17941823                           : 1; /* Legacy guest control (VBox < 4.3). */
    17951824    /* Build revision is ignored. */
     1825
     1826    LogFlowThisFunc(("uVerAdditions=%RU32 (%RU32.%RU32), mProtocolVersion=%RU32\n",
     1827                     uVerAdditions, uVBoxMajor, uVBoxMinor, mData.mProtocolVersion));
    17961828
    17971829    /* Tell the user but don't bitch too often. */
     
    17991831    if (s_gctrlLegacyWarning++ < 3) /** @todo Find a bit nicer text. */
    18001832        LogRel((tr("Warning: Guest Additions are older (%ld.%ld) than host capabilities for guest control, please upgrade them. Using protocol version %ld now\n"),
    1801                 VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions), VBOX_FULL_VERSION_GET_MINOR(uVerAdditions), mData.mProtocolVersion));
    1802  #endif
    1803 #endif
     1833                uVBoxMajor, uVBoxMinor, mData.mProtocolVersion));
     1834
    18041835    return VINF_SUCCESS;
    18051836}
     
    18141845                     fWaitFlags, uTimeoutMS, mData.mStatus, mData.mWaitCount, mData.mWaitEvent, pGuestRc));*/
    18151846
    1816     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1847    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    18171848
    18181849    /* Did some error occur before? Then skip waiting and return. */
     
    18261857    }
    18271858
     1859    /* Guest Additions < 4.3 don't support session handling, skip. */
     1860    if (mData.mProtocolVersion < 2)
     1861    {
     1862        waitResult = GuestSessionWaitResult_WaitFlagNotSupported;
     1863
     1864        LogFlowThisFunc(("Installed Guest Additions don't support waiting for dedicated sessions, skipping\n"));
     1865        return VINF_SUCCESS;
     1866    }
     1867
    18281868    waitResult = GuestSessionWaitResult_None;
    18291869    if (fWaitFlags & GuestSessionWaitForFlag_Terminate)
     
    19111951        eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged);
    19121952
    1913         vrc = registerEvent(mData.mSession.mID, 0 /* Object ID */,
    1914                             eventTypes, &pEvent);
     1953        vrc = registerWaitEvent(mData.mSession.mID, 0 /* Object ID */,
     1954                                eventTypes, &pEvent);
    19151955    }
    19161956    catch (std::bad_alloc)
     
    19561996    }
    19571997
    1958     unregisterEvent(pEvent);
     1998    unregisterWaitEvent(pEvent);
    19591999
    19602000    LogFlowFuncLeaveRC(vrc);
     
    20182058
    20192059    /* Close session on guest. */
    2020     int guestRc;
     2060    int guestRc = VINF_SUCCESS;
    20212061    int rc = closeSession(0 /* Flags */, 30 * 1000 /* Timeout */,
    20222062                          &guestRc);
     
    20292069        rc = rc2;
    20302070
    2031     /*
    2032      * Release autocaller before calling uninit.
    2033      */
    2034     autoCaller.release();
    2035 
    2036     uninit();
    2037 
    2038     LogFlowFuncLeaveRC(rc);
     2071    LogFlowThisFunc(("Returning rc=%Rrc, guestRc=%Rrc\n",
     2072                     rc, guestRc));
    20392073    if (RT_FAILURE(rc))
    20402074    {
     
    28542888    LogFlowThisFuncEnter();
    28552889
    2856     com::SafeArray<LONG> affinity;
     2890    com::SafeArray<LONG> affinityIgnored;
    28572891
    28582892    return ProcessCreateEx(aCommand, ComSafeArrayInArg(aArguments), ComSafeArrayInArg(aEnvironment),
    2859                            ComSafeArrayInArg(aFlags), aTimeoutMS, ProcessPriority_Default, ComSafeArrayAsInParam(affinity), aProcess);
     2893                           ComSafeArrayInArg(aFlags), aTimeoutMS, ProcessPriority_Default, ComSafeArrayAsInParam(affinityIgnored), aProcess);
    28602894#endif /* VBOX_WITH_GUEST_CONTROL */
    28612895}
  • trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp

    r46524 r47469  
    186186    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    187187
    188     int vrc = pSession->startSessionIntenal(pGuestRc);
     188    int vrc = pSession->startSessionInternal(pGuestRc);
    189189    /* Nothing to do here anymore. */
    190190
     
    319319    rc = pSession->processCreateExInteral(procInfo, pProcess);
    320320    if (RT_SUCCESS(rc))
    321         rc = pProcess->startProcess(&guestRc);
     321        rc = pProcess->startProcess(30 * 1000 /* 30s timeout */,
     322                                    &guestRc);
    322323    if (RT_FAILURE(rc))
    323324    {
     
    462463        } /* for */
    463464
    464         LogFlowThisFunc(("Copy loop ended with rc=%Rrc\n" ,rc));
     465        LogFlowThisFunc(("Copy loop ended with rc=%Rrc, cbWrittenTotal=%RU64, cbFileSize=%RU64\n",
     466                         rc, cbWrittenTotal, mSourceSize));
    465467
    466468        if (   !fCanceled
     
    531533        }
    532534
    533         if (!pProcess.isNull())
    534             pProcess->uninit();
     535        pProcess->Release();
    535536    } /* processCreateExInteral */
    536537
     
    638639            rc = pSession->processCreateExInteral(procInfo, pProcess);
    639640            if (RT_SUCCESS(rc))
    640                 rc = pProcess->startProcess(&guestRc);
     641                rc = pProcess->startProcess(30 * 1000 /* 30s timeout */,
     642                                            &guestRc);
    641643            if (RT_FAILURE(rc))
    642644            {
     
    802804                }
    803805
    804                 if (!pProcess.isNull())
    805                     pProcess->uninit();
     806                pProcess->Release();
    806807            }
    807808
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