VirtualBox

Changeset 48431 in vbox for trunk/src


Ignore:
Timestamp:
Sep 11, 2013 2:08:36 PM (11 years ago)
Author:
vboxsync
Message:

Main/Machine+Session: New generic client session watcher implementation based on token objects, works on all platforms and is used for now on XPCOM. Additionally a better error message when several API clients are racing for a lock, previously it could be quite confusing.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/Makefile.kmk

    r48406 r48431  
    5050  $(error "VBox: VBOX_WITH_XPCOM isn't defined")
    5151 endif
    52  ifneq ($(KBUILD_TARGET),os2)
    53   VBOX_MAIN_DEFS += VBOX_WITH_SYS_V_IPC_SESSION_WATCHER
    54  endif
     52 VBOX_MAIN_DEFS += VBOX_WITH_GENERIC_SESSION_WATCHER
    5553endif
    5654VBOX_MAIN_DEFS += \
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r48406 r48431  
    1747917479  <interface
    1748017480    name="IInternalSessionControl" extends="$unknown"
    17481     uuid="41506410-03d3-4b0c-9b27-e8e5149ce775"
     17481    uuid="2d2124a7-0f62-4907-ae21-eee5a559bdde"
    1748217482    internal="yes"
    1748317483    wsmap="suppress"
     
    1754117541      <param name="machine" type="IMachine" dir="in"/>
    1754217542      <param name="lockType" type="LockType" dir="in"/>
    17543       <param name="tokenId" type="wstring" dir="in"/>
     17543      <param name="token" type="IToken" dir="in"/>
    1754417544    </method>
    1754517545</if>
  • trunk/src/VBox/Main/include/ClientToken.h

    r47561 r48431  
    33/** @file
    44 *
    5  * VirtualBox API client token abstraction
     5 * VirtualBox API client session token abstraction
    66 */
    77
     
    2525
    2626#include "MachineImpl.h"
     27#ifdef VBOX_WITH_GENERIC_SESSION_WATCHER
     28# include "TokenImpl.h"
     29#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
    2730
    2831#if defined(RT_OS_WINDOWS)
     
    3538# define CTTOKENARG -1
    3639# define CTTOKENTYPE int
     40#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
     41# define CTTOKENARG NULL
     42# define CTTOKENTYPE MachineToken *
    3743#else
    3844# error "Port me!"
     
    4955     * Constructor which creates a usable instance
    5056     *
    51      * @param pMachine  Reference to Machine object
     57     * @param pMachine          Reference to Machine object
     58     * @param pSessionMachine   Reference to corresponding SessionMachine object
    5259     */
    53     ClientToken(const ComObjPtr<Machine> &pMachine);
     60    ClientToken(const ComObjPtr<Machine> &pMachine, SessionMachine *pSessionMachine);
    5461
    5562    /**
     
    7481    CTTOKENTYPE getToken();
    7582
     83#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    7684    /**
    7785     * Release token now. Returns information if the client has terminated.
    7886     */
    7987    bool release();
     88#endif /* !VBOX_WITH_GENERIC_SESSION_WATCHER */
    8089
    8190private:
     
    8897    CTTOKENTYPE mClientToken;
    8998    Utf8Str mClientTokenId;
     99#ifdef VBOX_WITH_GENERIC_SESSION_WATCHER
     100    bool mClientTokenPassed;
     101#endif
    90102};
    91103
  • trunk/src/VBox/Main/include/ClientTokenHolder.h

    r47561 r48431  
    33/** @file
    44 *
    5  * VirtualBox API client token holder (in the client process)
     5 * VirtualBox API client session token holder (in the client process)
    66 */
    77
     
    3535# define CTHSEMARG -1
    3636# define CTHSEMTYPE int
     37#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
     38/* the token object based implementation needs no semaphores */
    3739#else
    3840# error "Port me!"
     
    4648{
    4749public:
     50#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    4851    /**
    4952     * Constructor which creates a usable instance
     
    5255     */
    5356    ClientTokenHolder(const Utf8Str &strTokenId);
     57#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     58    /**
     59     * Constructor which creates a usable instance
     60     *
     61     * @param aToken        Reference to token object
     62     */
     63    ClientTokenHolder(IToken *aToken);
     64#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
    5465
    5566    /**
     
    6980    ClientTokenHolder();
    7081
     82#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    7183    Utf8Str mClientTokenId;
     84#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     85    ComPtr<IToken> mToken;
     86#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     87#ifdef CTHSEMTYPE
    7288    CTHSEMTYPE mSem;
     89#endif
     90#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
    7391    RTTHREAD mThread;
     92#endif
    7493#ifdef RT_OS_WINDOWS
    7594    CTHTHREADSEMTYPE mThreadSem;
  • trunk/src/VBox/Main/include/ClientWatcher.h

    r47561 r48431  
    33/** @file
    44 *
    5  * VirtualBox API client watcher
     5 * VirtualBox API client session watcher
    66 */
    77
     
    3333# define CWUPDATEREQARG NIL_RTSEMEVENT
    3434# define CWUPDATEREQTYPE RTSEMEVENT
    35 #elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
    36 # define CWUPDATEREQARG
     35#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) || defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
     36# define CWUPDATEREQARG NIL_RTSEMEVENT
    3737# define CWUPDATEREQTYPE RTSEMEVENT
    3838#else
     
    8080    ProcessList mProcesses;
    8181
    82 #ifdef VBOX_WITH_SYS_V_IPC_SESSION_WATCHER
     82#if defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) || defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
    8383    uint8_t mUpdateAdaptCtr;
    8484#endif
  • trunk/src/VBox/Main/include/MachineImpl.h

    r48406 r48431  
    788788    { return isSessionOpen(aMachine, aControl, true /* aAllowClosing */); }
    789789
     790#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    790791    bool checkForSpawnFailure();
     792#endif /* !VBOX_WITH_GENERIC_SESSION_WATCHER */
    791793
    792794    HRESULT prepareRegister();
     
    10341036    void FinalRelease();
    10351037
     1038    struct Uninit
     1039    {
     1040        enum Reason { Unexpected, Abnormal, Normal };
     1041    };
     1042
    10361043    // public initializer/uninitializer for internal purposes only
    10371044    HRESULT init(Machine *aMachine);
    10381045    void uninit() { uninit(Uninit::Unexpected); }
     1046    void uninit(Uninit::Reason aReason);
     1047
    10391048
    10401049    // util::Lockable interface
     
    10961105    }
    10971106
     1107#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    10981108    bool checkForDeath();
    10991109
    11001110    void getTokenId(Utf8Str &strTokenId);
     1111#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     1112    IToken *getToken();
     1113#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
    11011114    // getClientToken must be only used by callers who can guarantee that
    11021115    // the object cannot be deleted in the mean time, i.e. have a caller/lock.
     
    11521165    };
    11531166
    1154     struct Uninit
    1155     {
    1156         enum Reason { Unexpected, Abnormal, Normal };
    1157     };
    1158 
    11591167    struct SnapshotTask;
    11601168    struct DeleteSnapshotTask;
     
    11631171    friend struct DeleteSnapshotTask;
    11641172    friend struct RestoreSnapshotTask;
    1165 
    1166     void uninit(Uninit::Reason aReason);
    11671173
    11681174    HRESULT endSavingState(HRESULT aRC, const Utf8Str &aErrMsg);
  • trunk/src/VBox/Main/include/SessionImpl.h

    r48297 r48431  
    7272    STDMETHOD(GetPID)(ULONG *aPid);
    7373    STDMETHOD(GetRemoteConsole)(IConsole **aConsole);
     74#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    7475    STDMETHOD(AssignMachine)(IMachine *aMachine, LockType_T aLockType, IN_BSTR aTokenId);
     76#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     77    STDMETHOD(AssignMachine)(IMachine *aMachine, LockType_T aLockType, IToken *aToken);
     78#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
    7579    STDMETHOD(AssignRemoteMachine)(IMachine *aMachine, IConsole *aConsole);
    7680    STDMETHOD(UpdateMachineState)(MachineState_T aMachineState);
  • trunk/src/VBox/Main/include/TokenImpl.h

    r48297 r48431  
    4040    // public initializer/uninitializer for internal purposes only
    4141    HRESULT init(const ComObjPtr<SessionMachine> &pSessionMachine);
    42     void uninit();
     42    void uninit(bool fAbandon);
    4343
    4444private:
  • trunk/src/VBox/Main/src-client/ClientTokenHolder.cpp

    r47561 r48431  
    11/** @file
    22 *
    3  * VirtualBox API client token holder (in the client process)
     3 * VirtualBox API client session token holder (in the client process)
    44 */
    55
     
    101101    }
    102102
     103#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
     104
     105    if (!mToken.isNull())
     106    {
     107        mToken->Abandon();
     108        mToken.setNull();
     109    }
     110
    103111#else
    104112# error "Port me!"
     
    106114}
    107115
     116#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    108117Session::ClientTokenHolder::ClientTokenHolder(const Utf8Str &strTokenId) :
    109118    mClientTokenId(strTokenId)
    110 {
     119#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     120Session::ClientTokenHolder::ClientTokenHolder(IToken *aToken) :
     121    mToken(aToken)
     122#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     123{
     124#ifdef CTHSEMTYPE
    111125    mSem = CTHSEMARG;
     126#endif
     127#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
    112128    mThread = NIL_RTTHREAD;
     129#endif
    113130
    114131#if defined(RT_OS_WINDOWS)
     
    200217    mSem = s;
    201218
     219#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
     220
     221    /* nothing to do */
     222
    202223#else
    203224# error "Port me!"
     
    207228bool Session::ClientTokenHolder::isReady()
    208229{
     230#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    209231    return mSem != CTHSEMARG;
     232#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     233    return !mToken.isNull();
     234#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
    210235}
    211236
  • trunk/src/VBox/Main/src-client/SessionImpl.cpp

    r48299 r48431  
    294294}
    295295
     296#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    296297STDMETHODIMP Session::AssignMachine(IMachine *aMachine, LockType_T aLockType,
    297298                                    IN_BSTR aTokenId)
     299#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     300STDMETHODIMP Session::AssignMachine(IMachine *aMachine, LockType_T aLockType,
     301                                    IToken *aToken)
     302#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
    298303{
    299304    LogFlowThisFuncEnter();
     
    338343#endif
    339344
     345#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    340346    Utf8Str strTokenId(aTokenId);
    341347    Assert(!strTokenId.isEmpty());
     348#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     349    AssertPtr(aToken);
     350#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
    342351    /* create the machine client token */
    343352    try
    344353    {
     354#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    345355        mClientTokenHolder = new ClientTokenHolder(strTokenId);
     356#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     357        mClientTokenHolder = new ClientTokenHolder(aToken);
     358#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
    346359        if (!mClientTokenHolder->isReady())
    347360        {
  • trunk/src/VBox/Main/src-server/ClientToken.cpp

    r47561 r48431  
    11/** @file
    22 *
    3  * VirtualBox API client crash token handling
     3 * VirtualBox API client session crash token handling
    44 */
    55
     
    5858    mClientTokenId = "0";
    5959# endif /* VBOX_WITH_NEW_SYS_V_KEYGEN */
     60#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
     61    /* release the token, uses reference counting */
     62    if (mClientToken)
     63    {
     64        if (!mClientTokenPassed)
     65            mClientToken->Release();
     66        mClientToken = NULL;
     67    }
    6068#else
    6169# error "Port me!"
     
    6472}
    6573
    66 Machine::ClientToken::ClientToken(const ComObjPtr<Machine> &pMachine) :
     74Machine::ClientToken::ClientToken(const ComObjPtr<Machine> &pMachine,
     75                                  SessionMachine *pSessionMachine) :
    6776    mMachine(pMachine)
    6877{
    6978#if defined(RT_OS_WINDOWS)
     79    NOREF(pSessionMachine);
    7080    Bstr tokenId = pMachine->mData->m_strConfigFileFull;
    7181    for (size_t i = 0; i < tokenId.length(); i++)
     
    7888               mClientTokenId.c_str(), ::GetLastError()));
    7989#elif defined(RT_OS_OS2)
     90    NOREF(pSessionMachine);
    8091    Utf8Str ipcSem = Utf8StrFmt("\\SEM32\\VBOX\\VM\\{%RTuuid}",
    8192                                pMachine->mData->mUuid.raw());
     
    8697               ipcSem.c_str(), arc));
    8798#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
     99    NOREF(pSessionMachine);
    88100# ifdef VBOX_WITH_NEW_SYS_V_KEYGEN
    89101#  if defined(RT_OS_FREEBSD) && (HC_ARCH_BITS == 64)
     
    158170        AssertMsgFailedReturnVoid(("Cannot init token, errno=%d", errnoSave));
    159171    }
     172#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
     173    ComObjPtr<MachineToken> pToken;
     174    HRESULT rc = pToken.createObject();
     175    if (SUCCEEDED(rc))
     176    {
     177        rc = pToken->init(pSessionMachine);
     178        if (SUCCEEDED(rc))
     179        {
     180            mClientToken = pToken;
     181            if (mClientToken)
     182            {
     183                rc = mClientToken->AddRef();
     184                if (FAILED(rc))
     185                    mClientToken = NULL;
     186            }
     187        }
     188    }
     189    pToken.setNull();
     190    mClientTokenPassed = false;
     191    /* mClientTokenId isn't really used */
     192    mClientTokenId = pMachine->mData->m_strConfigFileFull;
     193    AssertMsg(mClientToken,
     194              ("Cannot create token '%s', rc=%Rhrc",
     195               mClientTokenId.c_str(), rc));
    160196#else
    161197# error "Port me!"
     
    175211CTTOKENTYPE Machine::ClientToken::getToken()
    176212{
     213#ifdef VBOX_WITH_GENERIC_SESSION_WATCHER
     214    mClientTokenPassed = true;
     215#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
    177216    return mClientToken;
    178217}
    179218
     219#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    180220bool Machine::ClientToken::release()
    181221{
     
    202242        terminated = true;
    203243    }
     244#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
     245    /** @todo r=klaus never tested, this code is not reached */
     246    AssertMsg(mClientToken, ("token must be created"));
     247    /* release the token, uses reference counting */
     248    if (mClientToken)
     249    {
     250        if (!mClientTokenPassed)
     251            mClientToken->Release();
     252        mClientToken = NULL;
     253    }
     254    terminated = true;
    204255#else
    205256# error "Port me!"
     
    207258    return terminated;
    208259}
     260#endif /* !VBOX_WITH_GENERIC_SESSION_WATCHER */
    209261
    210262/* vi: set tabstop=4 shiftwidth=4 expandtab: */
  • trunk/src/VBox/Main/src-server/ClientWatcher.cpp

    r48068 r48431  
    11/** @file
    22 *
    3  * VirtualBox API client crash watcher
     3 * VirtualBox API client session crash watcher
    44 */
    55
     
    3333#include "MachineImpl.h"
    3434
    35 #ifdef VBOX_WITH_SYS_V_IPC_SESSION_WATCHER
     35#if defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) || defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
    3636/** Table for adaptive timeouts. After an update the counter starts at the
    3737 * maximum value and decreases to 0, i.e. first the short timeouts are used
     
    6666        mUpdateReq = NULL;
    6767    }
    68 #elif defined(RT_OS_OS2) || defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
     68#elif defined(RT_OS_OS2) || defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) || defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
    6969    if (mUpdateReq != NIL_RTSEMEVENT)
    7070    {
     
    8787#elif defined(RT_OS_OS2)
    8888    RTSemEventCreate(&mUpdateReq);
    89 #elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
     89#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) || defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
    9090    RTSemEventCreate(&mUpdateReq);
    9191    /* start with high timeouts, nothing to do */
     
    125125    /* use short timeouts, as we expect changes */
    126126    ASMAtomicUoWriteU8(&mUpdateAdaptCtr, RT_ELEMENTS(s_aUpdateTimeoutSteps) - 1);
     127    RTSemEventSignal(mUpdateReq);
     128#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
    127129    RTSemEventSignal(mUpdateReq);
    128130#else
     
    688690    spawnedMachines.clear();
    689691
     692#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
     693
     694    bool update = false;
     695    bool updateSpawned = false;
     696
     697    do
     698    {
     699        AutoCaller autoCaller(that->mVirtualBox);
     700        if (!autoCaller.isOk())
     701            break;
     702
     703        do
     704        {
     705            /* release the caller to let uninit() ever proceed */
     706            autoCaller.release();
     707
     708            /* determine wait timeout adaptively: after updating information
     709             * relevant to the client watcher, check a few times more
     710             * frequently. This ensures good reaction time when the signalling
     711             * has to be done a bit before the actual change for technical
     712             * reasons, and saves CPU cycles when no activities are expected. */
     713            RTMSINTERVAL cMillies;
     714            {
     715                uint8_t uOld, uNew;
     716                do
     717                {
     718                    uOld = ASMAtomicUoReadU8(&that->mUpdateAdaptCtr);
     719                    uNew = uOld ? uOld - 1 : uOld;
     720                } while (!ASMAtomicCmpXchgU8(&that->mUpdateAdaptCtr, uNew, uOld));
     721                Assert(uOld <= RT_ELEMENTS(s_aUpdateTimeoutSteps) - 1);
     722                cMillies = s_aUpdateTimeoutSteps[uOld];
     723            }
     724
     725            int rc = RTSemEventWait(that->mUpdateReq, cMillies);
     726
     727            /*
     728             *  Restore the caller before using VirtualBox. If it fails, this
     729             *  means VirtualBox is being uninitialized and we must terminate.
     730             */
     731            autoCaller.add();
     732            if (!autoCaller.isOk())
     733                break;
     734
     735            if (RT_SUCCESS(rc) || update || updateSpawned)
     736            {
     737                /* RT_SUCCESS(rc) means an update event is signaled */
     738
     739#if 0
     740                // get reference to the machines list in VirtualBox
     741                VirtualBox::MachinesOList &allMachines = that->mVirtualBox->getMachinesList();
     742
     743                // lock the machines list for reading
     744                AutoReadLock thatLock(allMachines.getLockHandle() COMMA_LOCKVAL_SRC_POS);
     745
     746                if (RT_SUCCESS(rc) || update)
     747                {
     748                    /* obtain a new set of opened machines */
     749                    machines.clear();
     750
     751                    for (MachinesOList::iterator it = allMachines.begin();
     752                         it != allMachines.end();
     753                         ++it)
     754                    {
     755                        ComObjPtr<SessionMachine> sm;
     756                        if ((*it)->isSessionOpenOrClosing(sm))
     757                            machines.push_back(sm);
     758                    }
     759
     760                    cnt = machines.size();
     761                    LogFlowFunc(("UPDATE: direct session count = %d\n", cnt));
     762                }
     763
     764                if (RT_SUCCESS(rc) || updateSpawned)
     765                {
     766                    /* obtain a new set of spawned machines */
     767                    spawnedMachines.clear();
     768
     769                    for (MachinesOList::iterator it = allMachines.begin();
     770                         it != allMachines.end();
     771                         ++it)
     772                    {
     773                        if ((*it)->isSessionSpawning())
     774                            spawnedMachines.push_back(*it);
     775                    }
     776
     777                    cntSpawned = spawnedMachines.size();
     778                    LogFlowFunc(("UPDATE: spawned session count = %d\n", cntSpawned));
     779                }
     780
     781                // machines lock unwinds here
     782#endif
     783            }
     784
     785#if 0
     786            update = false;
     787            for (size_t i = 0; i < cnt; ++i)
     788                update |= (machines[i])->checkForDeath();
     789
     790            updateSpawned = false;
     791            for (size_t i = 0; i < cntSpawned; ++i)
     792                updateSpawned |= (spawnedMachines[i])->checkForSpawnFailure();
     793#endif
     794
     795            /* reap child processes */
     796            {
     797                AutoWriteLock alock(that->mLock COMMA_LOCKVAL_SRC_POS);
     798                if (that->mProcesses.size())
     799                {
     800                    LogFlowFunc(("UPDATE: child process count = %d\n",
     801                                 that->mProcesses.size()));
     802                    VirtualBox::ClientWatcher::ProcessList::iterator it = that->mProcesses.begin();
     803                    while (it != that->mProcesses.end())
     804                    {
     805                        RTPROCESS pid = *it;
     806                        RTPROCSTATUS status;
     807                        int vrc = ::RTProcWait(pid, RTPROCWAIT_FLAGS_NOBLOCK, &status);
     808                        if (vrc == VINF_SUCCESS)
     809                        {
     810                            if (   status.enmReason != RTPROCEXITREASON_NORMAL
     811                                || status.iStatus   != RTEXITCODE_SUCCESS)
     812                            {
     813                                switch (status.enmReason)
     814                                {
     815                                    default:
     816                                    case RTPROCEXITREASON_NORMAL:
     817                                        LogRel(("Reaper: Pid %d (%x) exited normally: %d (%#x)\n",
     818                                                pid, pid, status.iStatus, status.iStatus));
     819                                        break;
     820                                    case RTPROCEXITREASON_ABEND:
     821                                        LogRel(("Reaper: Pid %d (%x) abended: %d (%#x)\n",
     822                                                pid, pid, status.iStatus, status.iStatus));
     823                                        break;
     824                                    case RTPROCEXITREASON_SIGNAL:
     825                                        LogRel(("Reaper: Pid %d (%x) was signalled: %d (%#x)\n",
     826                                                pid, pid, status.iStatus, status.iStatus));
     827                                        break;
     828                                }
     829                            }
     830                            else
     831                                LogFlowFunc(("pid %d (%x) was reaped, status=%d, reason=%d\n",
     832                                             pid, pid, status.iStatus,
     833                                             status.enmReason));
     834                            it = that->mProcesses.erase(it);
     835                        }
     836                        else
     837                        {
     838                            LogFlowFunc(("pid %d (%x) was NOT reaped, vrc=%Rrc\n",
     839                                         pid, pid, vrc));
     840                            if (vrc != VERR_PROCESS_RUNNING)
     841                            {
     842                                /* remove the process if it is not already running */
     843                                it = that->mProcesses.erase(it);
     844                            }
     845                            else
     846                                ++it;
     847                        }
     848                    }
     849                }
     850            }
     851        }
     852        while (true);
     853    }
     854    while (0);
     855
     856    /* release sets of machines if any */
     857    machines.clear();
     858    spawnedMachines.clear();
     859
    690860#else
    691861# error "Port me!"
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r48406 r48431  
    36173617        if (fLaunchingVMProcess)
    36183618        {
     3619            if (mData->mSession.mPID == NIL_RTPROCESS)
     3620            {
     3621                // two or more clients racing for a lock, the one which set the
     3622                // session state to Spawning will win, the others will get an
     3623                // error as we can't decide here if waiting a little would help
     3624                // (only for shared locks this would avoid an error)
     3625                return setError(VBOX_E_INVALID_OBJECT_STATE,
     3626                                tr("The machine '%s' already has a lock request pending"),
     3627                                mUserData->s.strName.c_str());
     3628            }
     3629
    36193630            // this machine is awaiting for a spawning session to be opened:
    36203631            // then the calling process must be the one that got started by
     
    36533664            mData->mSession.mState = SessionState_Spawning;
    36543665
     3666#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    36553667            /* Get the client token ID to be passed to the client process */
    36563668            Utf8Str strTokenId;
    36573669            sessionMachine->getTokenId(strTokenId);
    36583670            Assert(!strTokenId.isEmpty());
     3671#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     3672            /* Get the client token to be passed to the client process */
     3673            ComPtr<IToken> pToken(sessionMachine->getToken());
     3674            /* The token is now "owned" by pToken, fix refcount */
     3675            if (!pToken.isNull())
     3676                pToken->Release();
     3677#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
    36593678
    36603679            /*
     
    36713690
    36723691            LogFlowThisFunc(("Calling AssignMachine()...\n"));
     3692#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    36733693            rc = pSessionControl->AssignMachine(sessionMachine, lockType, Bstr(strTokenId).raw());
     3694#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     3695            rc = pSessionControl->AssignMachine(sessionMachine, lockType, pToken);
     3696            /* Now the token is owned by the client process. */
     3697            pToken.setNull();
     3698#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
    36743699            LogFlowThisFunc(("AssignMachine() returned %08X\n", rc));
    36753700
     
    80768101    /* inform the session that it will be a remote one */
    80778102    LogFlowThisFunc(("Calling AssignMachine (NULL)...\n"));
     8103#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    80788104    HRESULT rc = aControl->AssignMachine(NULL, LockType_Write, Bstr::Empty.raw());
     8105#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     8106    HRESULT rc = aControl->AssignMachine(NULL, LockType_Write, NULL);
     8107#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
    80798108    LogFlowThisFunc(("AssignMachine (NULL) returned %08X\n", rc));
    80808109
     
    81668195}
    81678196
     8197#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    81688198/**
    81698199 * Called from the client watcher thread to check for unexpected client process
     
    82598289    return false;
    82608290}
     8291#endif /* !VBOX_WITH_GENERIC_SESSION_WATCHER */
    82618292
    82628293/**
     
    1264512676    try
    1264612677    {
    12647         mClientToken = new ClientToken(aMachine);
     12678        mClientToken = new ClientToken(aMachine, this);
    1264812679        if (!mClientToken->isReady())
    1264912680        {
     
    1274412775/**
    1274512776 *  Uninitializes this session object. If the reason is other than
    12746  *  Uninit::Unexpected, then this method MUST be called from #checkForDeath().
     12777 *  Uninit::Unexpected, then this method MUST be called from #checkForDeath()
     12778 *  or the client watcher code.
    1274712779 *
    1274812780 *  @param aReason          uninitialization reason
     
    1299113023    multilock.release();
    1299213024
    12993     RTThreadSleep(500);
    12994     mParent->AddRef();
    12995     LONG c = mParent->Release();
    12996     LogFlowThisFunc(("vbox ref=%d\n", c)); NOREF(c);
    1299713025    unconst(mParent) = NULL;
    1299813026    unconst(mPeer) = NULL;
     
    1383813866/////////////////////////////////////////////////////////////////////////////
    1383913867
     13868#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    1384013869/**
    1384113870 * Called from the client watcher thread to check for expected or unexpected
     
    1390613935        mClientToken->getId(strTokenId);
    1390713936}
     13937#else /* VBOX_WITH_GENERIC_SESSION_WATCHER */
     13938IToken *SessionMachine::getToken()
     13939{
     13940    LogFlowThisFunc(("\n"));
     13941
     13942    AutoCaller autoCaller(this);
     13943    AssertComRCReturn(autoCaller.rc(), NULL);
     13944
     13945    Assert(mClientToken);
     13946    if (mClientToken)
     13947        return mClientToken->getToken();
     13948    else
     13949        return NULL;
     13950}
     13951#endif /* VBOX_WITH_GENERIC_SESSION_WATCHER */
    1390813952
    1390913953Machine::ClientToken *SessionMachine::getClientToken()
  • trunk/src/VBox/Main/src-server/TokenImpl.cpp

    r48305 r48431  
    3535void MachineToken::FinalRelease()
    3636{
    37     uninit();
     37    uninit(false);
    3838
    3939    BaseFinalRelease();
     
    7070 * Called either from FinalRelease() or by the parent when it gets destroyed.
    7171 */
    72 void MachineToken::uninit()
     72void MachineToken::uninit(bool fAbandon)
    7373{
    7474    LogFlowThisFunc(("\n"));
     
    8282    if (!m.pSessionMachine.isNull())
    8383    {
    84         m.pSessionMachine->uninit();
     84        m.pSessionMachine->uninit(fAbandon ? SessionMachine::Uninit::Normal : SessionMachine::Uninit::Abnormal);
    8585        m.pSessionMachine.setNull();
    8686    }
     
    9696
    9797    /* uninit does everything we need */
    98     uninit();
     98    uninit(true);
    9999    return S_OK;
    100100}
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