VirtualBox

Changeset 13457 in vbox


Ignore:
Timestamp:
Oct 21, 2008 5:46:36 PM (16 years ago)
Author:
vboxsync
Message:

Main: Implemented detection of the unexpected spawning session termination for Windows (#3128), optimized for other platforms.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/MachineImpl.cpp

    r13455 r13457  
    31533153
    31543154/**
    3155  * Returns the session machine object associated with the this machine.
    3156  * The returned session machine is null if no direct session is currently open.
    3157  *
    3158  * @note locks this object for reading.
    3159  */
    3160 ComObjPtr <SessionMachine> Machine::sessionMachine()
    3161 {
    3162     ComObjPtr <SessionMachine> sm;
    3163 
    3164     AutoLimitedCaller autoCaller (this);
    3165     AssertComRCReturn (autoCaller.rc(), sm);
    3166 
    3167     /* return null for inaccessible machines */
    3168     if (autoCaller.state() != Ready)
    3169         return sm;
    3170 
    3171     AutoReadLock alock (this);
    3172 
    3173     sm = mData->mSession.mMachine;
    3174     Assert (!sm.isNull() ||
    3175             mData->mSession.mState != SessionState_Open);
    3176 
    3177     return  sm;
    3178 }
    3179 
    3180 /**
    3181  * Called from the client watcher thread to check for unexpected client process
    3182  * death during Session_Spawning state (e.g. before it successfully opened a
    3183  * direct session).
    3184  *
    3185  * This method returns @c true if the client process is terminated and @c false
    3186  * if it's still alive.
    3187  *
    3188  * @note Locks this object for writing.
    3189  */
    3190 bool Machine::checkForSpawnFailure()
    3191 {
    3192     AutoCaller autoCaller (this);
    3193     if (!autoCaller.isOk())
    3194     {
    3195         /* nothing to do */
    3196         LogFlowThisFunc (("Already uninitialized!"));
    3197         return true;
    3198     }
    3199 
    3200     /* VirtualBox::addProcessToReap() needs a write lock */
    3201     AutoMultiWriteLock2 alock (mParent, this);
    3202 
    3203     if (mData->mSession.mState != SessionState_Spawning)
    3204     {
    3205         /* nothing to do */
    3206         LogFlowThisFunc (("Not spawning any more!"));
    3207         return true;
    3208     }
    3209 
    3210     HRESULT rc = S_OK;
    3211 
    3212     RTPROCSTATUS status;
    3213     int vrc = ::RTProcWait (mData->mSession.mPid, RTPROCWAIT_FLAGS_NOBLOCK,
    3214                             &status);
    3215 
    3216     if (vrc != VERR_PROCESS_RUNNING)
    3217         rc = setError (E_FAIL,
    3218                        tr ("Virtual machine '%ls' has terminated unexpectedly "
    3219                            "during startup"),
    3220                        name().raw());
    3221 
    3222     if (FAILED (rc))
    3223     {
    3224         /* Close the remote session, remove the remote control from the list
    3225          * and reset session state to Closed (@note keep the code in sync with
    3226          * the relevant part in checkForSpawnFailure()). */
    3227 
    3228         Assert (mData->mSession.mRemoteControls.size() == 1);
    3229         if (mData->mSession.mRemoteControls.size() == 1)
    3230         {
    3231             ErrorInfoKeeper eik;
    3232             mData->mSession.mRemoteControls.front()->Uninitialize();
    3233         }
    3234 
    3235         mData->mSession.mRemoteControls.clear();
    3236         mData->mSession.mState = SessionState_Closed;
    3237 
    3238         /* finalize the progress after setting the state, for consistency */
    3239         mData->mSession.mProgress->notifyComplete (rc);
    3240         mData->mSession.mProgress.setNull();
    3241 
    3242         mParent->addProcessToReap (mData->mSession.mPid);
    3243         mData->mSession.mPid = NIL_RTPROCESS;
    3244 
    3245         mParent->onSessionStateChange (mData->mUuid, SessionState_Closed);
    3246         return true;
    3247     }
    3248 
    3249     return false;
    3250 }
    3251 
    3252 /**
    32533155 *  Saves the registry entry of this machine to the given configuration node.
    32543156 *
     
    40553957    LogFlowThisFuncLeave();
    40563958    return S_OK;
     3959}
     3960
     3961/**
     3962 * Returns @c true if the given machine has an open direct session and returns
     3963 * the session machine instance and additional session data (on some platforms)
     3964 * if so.
     3965 *
     3966 * Note that when the method returns @c false, the arguments remain unchanged.
     3967 *
     3968 * @param aMachine  Session machine object.
     3969 * @param aIPCSem   Mutex IPC semaphore handle for this machine.
     3970 *
     3971 * @note locks this object for reading.
     3972 */
     3973#if defined (RT_OS_WINDOWS)
     3974bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     3975                             HANDLE *aIPCSem /*= NULL*/)
     3976#elif defined (RT_OS_OS2)
     3977bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     3978                             HMTX *aIPCSem /*= NULL*/);
     3979#else
     3980bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine)
     3981#endif
     3982{
     3983    AutoLimitedCaller autoCaller (this);
     3984    AssertComRCReturn (autoCaller.rc(), false);
     3985
     3986    /* just return false for inaccessible machines */
     3987    if (autoCaller.state() != Ready)
     3988        return false;
     3989
     3990    AutoReadLock alock (this);
     3991
     3992    if (mData->mSession.mState == SessionState_Open)
     3993    {
     3994        AssertReturn (!mData->mSession.mMachine.isNull(), false);
     3995
     3996        aMachine = mData->mSession.mMachine;
     3997
     3998#if defined (RT_OS_WINDOWS) || defined (RT_OS_OS2)
     3999        /* Additional session data */
     4000        if (aIPCSem != NULL)
     4001            *aIPCSem = aMachine->mIPCSem;
     4002#endif
     4003        return true;
     4004    }
     4005
     4006    return false;
     4007}
     4008
     4009/**
     4010 * Returns @c true if the given machine has an spawning direct session and
     4011 * returns and additional session data (on some platforms) if so.
     4012 *
     4013 * Note that when the method returns @c false, the arguments remain unchanged.
     4014 *
     4015 * @param aPID  PID of the spawned direct session process.
     4016 *
     4017 * @note locks this object for reading.
     4018 */
     4019#if defined (RT_OS_WINDOWS) || defined (RT_OS_OS2)
     4020bool Machine::isSessionSpawning (RTPROCESS *aPID /*= NULL*/)
     4021#else
     4022bool Machine::isSessionSpawning()
     4023#endif
     4024{
     4025    AutoLimitedCaller autoCaller (this);
     4026    AssertComRCReturn (autoCaller.rc(), false);
     4027
     4028    /* just return false for inaccessible machines */
     4029    if (autoCaller.state() != Ready)
     4030        return false;
     4031
     4032    AutoReadLock alock (this);
     4033
     4034    if (mData->mSession.mState == SessionState_Spawning)
     4035    {
     4036#if defined (RT_OS_WINDOWS) || defined (RT_OS_OS2)
     4037        /* Additional session data */
     4038        if (aPID != NULL)
     4039        {
     4040            AssertReturn (mData->mSession.mPid != NIL_RTPROCESS, false);
     4041            *aPID = mData->mSession.mPid;
     4042        }
     4043#endif
     4044        return true;
     4045    }
     4046
     4047    return false;
     4048}
     4049
     4050/**
     4051 * Called from the client watcher thread to check for unexpected client process
     4052 * death during Session_Spawning state (e.g. before it successfully opened a
     4053 * direct session).
     4054 *
     4055 * On Win32 and on OS/2, this method is called only when we've got the
     4056 * direct client's process termination notification, so it always returns @c
     4057 * true.
     4058 *
     4059 * On other platforms, this method returns @c true if the client process is
     4060 * terminated and @c false if it's still alive.
     4061 *
     4062 * @note Locks this object for writing.
     4063 */
     4064bool Machine::checkForSpawnFailure()
     4065{
     4066    AutoCaller autoCaller (this);
     4067    if (!autoCaller.isOk())
     4068    {
     4069        /* nothing to do */
     4070        LogFlowThisFunc (("Already uninitialized!"));
     4071        return true;
     4072    }
     4073
     4074    /* VirtualBox::addProcessToReap() needs a write lock */
     4075    AutoMultiWriteLock2 alock (mParent, this);
     4076
     4077    if (mData->mSession.mState != SessionState_Spawning)
     4078    {
     4079        /* nothing to do */
     4080        LogFlowThisFunc (("Not spawning any more!"));
     4081        return true;
     4082    }
     4083
     4084    HRESULT rc = S_OK;
     4085
     4086#if defined (RT_OS_WINDOWS) || defined (RT_OS_OS2)
     4087
     4088    /* the process was already unexpectedly terminated, we just need to set an
     4089     * error and finalize session spawning */
     4090    rc = setError (E_FAIL,
     4091                   tr ("Virtual machine '%ls' has terminated unexpectedly "
     4092                       "during startup"),
     4093                   name().raw());
     4094#else
     4095
     4096    RTPROCSTATUS status;
     4097    int vrc = ::RTProcWait (mData->mSession.mPid, RTPROCWAIT_FLAGS_NOBLOCK,
     4098                            &status);
     4099
     4100    if (vrc != VERR_PROCESS_RUNNING)
     4101        rc = setError (E_FAIL,
     4102                       tr ("Virtual machine '%ls' has terminated unexpectedly "
     4103                           "during startup"),
     4104                       name().raw());
     4105#endif
     4106
     4107    if (FAILED (rc))
     4108    {
     4109        /* Close the remote session, remove the remote control from the list
     4110         * and reset session state to Closed (@note keep the code in sync with
     4111         * the relevant part in checkForSpawnFailure()). */
     4112
     4113        Assert (mData->mSession.mRemoteControls.size() == 1);
     4114        if (mData->mSession.mRemoteControls.size() == 1)
     4115        {
     4116            ErrorInfoKeeper eik;
     4117            mData->mSession.mRemoteControls.front()->Uninitialize();
     4118        }
     4119
     4120        mData->mSession.mRemoteControls.clear();
     4121        mData->mSession.mState = SessionState_Closed;
     4122
     4123        /* finalize the progress after setting the state, for consistency */
     4124        mData->mSession.mProgress->notifyComplete (rc);
     4125        mData->mSession.mProgress.setNull();
     4126
     4127        mParent->addProcessToReap (mData->mSession.mPid);
     4128        mData->mSession.mPid = NIL_RTPROCESS;
     4129
     4130        mParent->onSessionStateChange (mData->mUuid, SessionState_Closed);
     4131        return true;
     4132    }
     4133
     4134    return false;
    40574135}
    40584136
     
    93169394 * death of the client process that has a direct session to this machine.
    93179395 *
    9318  * @note On Win32 and on OS/2, this method is called only when we've got the
     9396 * On Win32 and on OS/2, this method is called only when we've got the
    93199397 * mutex (i.e. the client has either died or terminated normally) so it always
    93209398 * returns @c true (the client is terminated, the session machine is
    93219399 * uninitialized).
    93229400 *
    9323  * @note On Linux, the method returns @c true if the client process has
     9401 * On other platforms, the method returns @c true if the client process has
    93249402 * terminated normally or abnormally and the session machine was uninitialized,
    93259403 * and @c false if the client process is still alive.
  • trunk/src/VBox/Main/VirtualBoxImpl.cpp

    r13436 r13457  
    29302930
    29312931/**
    2932  *  Returns the list of opened machines (i.e. machines having direct sessions
    2933  *  opened by client processes).
    2934  *
    2935  *  @note the returned list contains smart pointers. So, clear it as soon as
    2936  *  it becomes no more necessary to release instances.
    2937  *  @note it can be possible that a session machine from the list has been
    2938  *  already uninitialized, so a) lock the instance and b) chheck for
    2939  *  instance->isReady() return value before manipulating the object directly
    2940  *  (i.e. not through COM methods).
    2941  *
    2942  *  @note Locks objects for reading.
     2932 * Returns the list of opened machines (machines having direct sessionsopened by
     2933 * client processes).
     2934 *
     2935 * @note The returned list contains smart pointers. So, clear it as soon as
     2936 * it becomes no more necessary to release instances.
     2937 *
     2938 * @note It can be possible that a session machine from the list has been
     2939 * already uninitialized, so do a usual AutoCaller/AutoReadLock sequence
     2940 * whenaccessing unprotected data directly.
     2941 *
     2942 * @note Locks objects for reading.
    29432943 */
    29442944void VirtualBox::getOpenedMachines (SessionMachineVector &aVector)
    29452945{
    29462946    AutoCaller autoCaller (this);
    2947     AssertComRCReturn (autoCaller.rc(), (void) 0);
    2948 
    2949     std::list <ComObjPtr <SessionMachine> > list;
    2950 
    2951     {
    2952         AutoReadLock alock (this);
    2953 
    2954         for (MachineList::iterator it = mData.mMachines.begin();
    2955              it != mData.mMachines.end();
    2956              ++ it)
    2957         {
    2958             ComObjPtr <SessionMachine> sm = (*it)->sessionMachine();
    2959             /* SessionMachine is null when there are no open sessions */
    2960             if (!sm.isNull())
    2961                 list.push_back (sm);
    2962         }
    2963     }
    2964 
    2965     aVector = SessionMachineVector (list.begin(), list.end());
    2966     return;
    2967 }
    2968 
    2969 /**
    2970  *  Returns the list of opened machines (i.e. machines having direct sessions
    2971  *  opened by client processes).
    2972  *
    2973  *  @note the returned list contains smart pointers. So, clear it as soon as
    2974  *  it becomes no more necessary to release instances.
    2975  *  @note it can be possible that a session machine from the list has been
    2976  *  already uninitialized, so a) lock the instance and b) chheck for
    2977  *  instance->isReady() return value before manipulating the object directly
    2978  *  (i.e. not through COM methods).
    2979  *
    2980  *  @note Locks objects for reading.
    2981  */
    2982 void VirtualBox::getSpawnedMachines (MachineVector &aVector)
    2983 {
    2984     AutoCaller autoCaller (this);
    2985     AssertComRCReturn (autoCaller.rc(), (void) 0);
    2986 
    2987     std::list <ComObjPtr <Machine> > list;
    2988 
    2989     {
    2990         AutoReadLock alock (this);
    2991 
    2992         for (MachineList::iterator it = mData.mMachines.begin();
    2993              it != mData.mMachines.end();
    2994              ++ it)
    2995         {
    2996             ComObjPtr <Machine> m = (*it);
    2997             SessionState_T state;
    2998             m->COMGETTER(SessionState(&state));
    2999             if (state == SessionState_Spawning)
    3000                 list.push_back (m);
    3001         }
    3002     }
    3003 
    3004     aVector = MachineVector (list.begin(), list.end());
    3005     return;
     2947    AssertComRCReturnVoid (autoCaller.rc());
     2948
     2949    aVector.clear();
     2950
     2951    AutoReadLock alock (this);
     2952
     2953    for (MachineList::iterator it = mData.mMachines.begin();
     2954         it != mData.mMachines.end();
     2955         ++ it)
     2956    {
     2957        ComObjPtr <SessionMachine> sm;
     2958        if ((*it)->isSessionOpen (sm))
     2959            aVector.push_back (sm);
     2960    }
    30062961}
    30072962
     
    47094664    SessionMachineVector machines;
    47104665    MachineVector spawnedMachines;
     4666
    47114667    size_t cnt = 0;
    47124668    size_t cntSpawned = 0;
     
    47214677    /// @todo (dmik) processes reaping!
    47224678
    4723     HANDLE *handles = new HANDLE [1];
     4679    HANDLE handles [MAXIMUM_WAIT_OBJECTS];
    47244680    handles [0] = that->mWatcherData.mUpdateReq;
    47254681
     
    47364692            autoCaller.release();
    47374693
    4738 #undef VBOX_CHECK_SPAWN_FAILURES
    4739 #ifdef VBOX_CHECK_SPAWN_FAILURES
    4740             DWORD rc = ::WaitForMultipleObjects (cnt + 1, handles, FALSE, 500);
    4741 #else
    4742             DWORD rc = ::WaitForMultipleObjects (cnt + 1, handles, FALSE, INFINITE);
    4743 #endif
    4744 
    4745             /*
    4746              *  Restore the caller before using VirtualBox. If it fails, this
    4747              *  means VirtualBox is being uninitialized and we must terminate.
    4748              */
     4694            DWORD rc = ::WaitForMultipleObjects (1 + cnt + cntSpawned,
     4695                                                 handles, FALSE, INFINITE);
     4696
     4697            /* Restore the caller before using VirtualBox. If it fails, this
     4698             * means VirtualBox is being uninitialized and we must terminate. */
    47494699            autoCaller.add();
    47504700            if (!autoCaller.isOk())
     
    47524702
    47534703            bool update = false;
    4754 #ifdef VBOX_CHECK_SPAWN_FAILURES
    4755             if (rc == WAIT_OBJECT_0 || rc == WAIT_TIMEOUT)
    4756 #else
     4704
    47574705            if (rc == WAIT_OBJECT_0)
    4758 #endif
    47594706            {
    47604707                /* update event is signaled */
     
    47734720                update = true;
    47744721            }
     4722            else if (rc > WAIT_OBJECT_0 + cnt && rc <= (WAIT_OBJECT_0 + cntSpawned))
     4723            {
     4724                /* spawned VM process has terminated (normally or abnormally) */
     4725                (spawnedMachines [rc - WAIT_OBJECT_0 - cnt - 1])->
     4726                    checkForSpawnFailure();
     4727                update = true;
     4728            }
     4729
    47754730            if (update)
    47764731            {
     4732                /* close old process handles */
     4733                for (size_t i = 1 + cnt; i < 1 + cnt + cntSpawned; ++ i)
     4734                    CloseHandle (handles [i]);
     4735
     4736                AutoReadLock thatLock (that);
     4737
    47774738                /* obtain a new set of opened machines */
    4778                 that->getOpenedMachines (machines);
    4779                 cnt = machines.size();
     4739                cnt = 0;
     4740                machines.clear();
     4741
     4742                for (MachineList::iterator it = that->mData.mMachines.begin();
     4743                     it != that->mData.mMachines.end(); ++ it)
     4744                {
     4745                    /// @todo handle situations with more than 64 objects
     4746                    AssertMsgBreak ((1 + cnt) <= MAXIMUM_WAIT_OBJECTS,
     4747                                    ("MAXIMUM_WAIT_OBJECTS reached"));
     4748
     4749                    ComObjPtr <SessionMachine> sm;
     4750                    HANDLE ipcSem;
     4751                    if ((*it)->isSessionOpen (sm, &ipcSem))
     4752                    {
     4753                        machines.push_back (sm);
     4754                        handles [1 + cnt] = ipcSem;
     4755                        ++ cnt;
     4756                    }
     4757                }
     4758
    47804759                LogFlowFunc (("UPDATE: direct session count = %d\n", cnt));
    4781                 AssertMsg ((cnt + 1) <= MAXIMUM_WAIT_OBJECTS,
    4782                            ("MAXIMUM_WAIT_OBJECTS reached"));
    4783                 /* renew the set of event handles */
    4784                 delete [] handles;
    4785                 handles = new HANDLE [cnt + 1];
    4786                 handles [0] = that->mWatcherData.mUpdateReq;
    4787                 for (size_t i = 0; i < cnt; ++ i)
    4788                     handles [i + 1] = (machines [i])->ipcSem();
    4789 
    4790 #ifdef VBOX_CHECK_SPAWN_FAILURES
    4791                 /* check for spawn errors */
    4792                 that->getSpawnedMachines (spawnedMachines);
    4793                 cntSpawned = spawnedMachines.size();
    4794                 for (size_t i = 0; i < cntSpawned; ++ i)
    4795                     (spawnedMachines [i])->checkForSpawnFailure();
    4796 #endif
     4760
     4761                /* obtain a new set of spawned machines */
     4762                cntSpawned = 0;
     4763                spawnedMachines.clear();
     4764
     4765                for (MachineList::iterator it = that->mData.mMachines.begin();
     4766                     it != that->mData.mMachines.end(); ++ it)
     4767                {
     4768                    /// @todo handle situations with more than 64 objects
     4769                    AssertMsgBreak ((1 + cnt + cntSpawned) <= MAXIMUM_WAIT_OBJECTS,
     4770                                    ("MAXIMUM_WAIT_OBJECTS reached"));
     4771
     4772                    RTPROCESS pid;
     4773                    if ((*it)->isSessionSpawning (&pid))
     4774                    {
     4775                        HANDLE ph = OpenProcess (SYNCHRONIZE, FALSE, pid);
     4776                        AssertMsg (ph != NULL, ("OpenProcess (pid=%d) failed with %d\n",
     4777                                                pid, GetLastError()));
     4778                        if (rc == 0)
     4779                        {
     4780                            spawnedMachines.push_back (*it);
     4781                            handles [1 + cnt + cntSpawned] = ph;
     4782                            ++ cntSpawned;
     4783                        }
     4784                    }
     4785                }
     4786
     4787                LogFlowFunc (("UPDATE: spawned session count = %d\n", cntSpawned));
    47974788            }
    47984789        }
     
    48014792    while (0);
    48024793
    4803     /* delete the set of event handles */
    4804     delete [] handles;
    4805 
    4806     /* delete the set of opened machines if any */
     4794    /* close old process handles */
     4795    for (size_t i = 1 + cnt; i < 1 + cnt + cntSpawned; ++ i)
     4796        CloseHandle (handles [i]);
     4797
     4798    /* release sets of machines if any */
    48074799    machines.clear();
     4800    spawnedMachines.clear();
    48084801
    48094802    ::CoUninitialize();
     
    48324825            int vrc = RTSemEventWait (that->mWatcherData.mUpdateReq, 500);
    48334826
    4834             /*
    4835              *  Restore the caller before using VirtualBox. If it fails, this
    4836              *  means VirtualBox is being uninitialized and we must terminate.
    4837              */
     4827            /* Restore the caller before using VirtualBox. If it fails, this
     4828             * means VirtualBox is being uninitialized and we must terminate. */
    48384829            autoCaller.add();
    48394830            if (!autoCaller.isOk())
     
    48414832
    48424833            bool update = false;
     4834            bool updateSpawned = false;
    48434835
    48444836            if (VBOX_SUCCESS (vrc))
     
    48464838                /* update event is signaled */
    48474839                update = true;
     4840                updateSpawned = true;
    48484841            }
    48494842            else
     
    49144907                                   ("DosWaitMuxWaitSem returned %d\n", arc));
    49154908                }
     4909
     4910                /* are there any spawning sessions? */
     4911                if (cntSpawned > 0)
     4912                {
     4913                    for (size_t i = 0; i < cntSpawned; ++ i)
     4914                        updateSpawned |= (spawnedMachines [i])->
     4915                            checkForSpawnFailure();
     4916                }
    49164917            }
    49174918
    4918             if (update)
     4919            if (update || updateSpawned)
    49194920            {
    4920                 /* close the old muxsem */
    4921                 if (muxSem != NULLHANDLE)
    4922                     ::DosCloseMuxWaitSem (muxSem);
    4923                 /* obtain a new set of opened machines */
    4924                 that->getOpenedMachines (machines);
    4925                 cnt = machines.size();
    4926                 LogFlowFunc (("UPDATE: direct session count = %d\n", cnt));
    4927                 /// @todo use several muxwait sems if cnt is > 64
    4928                 AssertMsg (cnt <= 64 /* according to PMREF */,
    4929                            ("maximum of 64 mutex semaphores reached (%d)", cnt));
    4930                 if (cnt > 64)
    4931                     cnt = 64;
    4932                 if (cnt > 0)
     4921                AutoReadLock thatLock (that);
     4922
     4923                if (update)
    49334924                {
    4934                     /* renew the set of event handles */
    4935                     for (size_t i = 0; i < cnt; ++ i)
     4925                    /* close the old muxsem */
     4926                    if (muxSem != NULLHANDLE)
     4927                        ::DosCloseMuxWaitSem (muxSem);
     4928
     4929                    /* obtain a new set of opened machines */
     4930                    cnt = 0;
     4931                    machines.clear();
     4932
     4933                    for (MachineList::iterator it = that->mData.mMachines.begin();
     4934                         it != that->mData.mMachines.end(); ++ it)
    49364935                    {
    4937                         handles [i].hsemCur = (HSEM) machines [i]->ipcSem();
    4938                         handles [i].ulUser = i;
     4936                        /// @todo handle situations with more than 64 objects
     4937                        AssertMsg (cnt <= 64 /* according to PMREF */,
     4938                                   ("maximum of 64 mutex semaphores reached (%d)",
     4939                                    cnt));
     4940
     4941                        ComObjPtr <SessionMachine> sm;
     4942                        HMTX ipcSem;
     4943                        if ((*it)->isSessionOpen (sm, &ipcSem))
     4944                        {
     4945                            machines.push_back (sm);
     4946                            handles [cnt].hsemCur = (HSEM) ipcSem;
     4947                            handles [cnt].ulUser = cnt;
     4948                            ++ cnt;
     4949                        }
    49394950                    }
    4940                     /* create a new muxsem */
    4941                     APIRET arc = ::DosCreateMuxWaitSem (NULL, &muxSem, cnt, handles,
    4942                                                         DCMW_WAIT_ANY);
    4943                     AssertMsg (arc == NO_ERROR,
    4944                                ("DosCreateMuxWaitSem returned %d\n", arc)); NOREF(arc);
     4951
     4952                    LogFlowFunc (("UPDATE: direct session count = %d\n", cnt));
     4953
     4954                    if (cnt > 0)
     4955                    {
     4956                        /* create a new muxsem */
     4957                        APIRET arc = ::DosCreateMuxWaitSem (NULL, &muxSem, cnt,
     4958                                                            handles,
     4959                                                            DCMW_WAIT_ANY);
     4960                        AssertMsg (arc == NO_ERROR,
     4961                                   ("DosCreateMuxWaitSem returned %d\n", arc));
     4962                        NOREF(arc);
     4963                    }
     4964                }
     4965
     4966                if (updateSpawned)
     4967                {
     4968                    /* obtain a new set of spawned machines */
     4969                    spawnedMachines.clear();
     4970
     4971                    for (MachineList::iterator it = that->mData.mMachines.begin();
     4972                         it != that->mData.mMachines.end(); ++ it)
     4973                    {
     4974                        if ((*it)->isSessionSpawning())
     4975                            spawnedMachines.push_back (*it);
     4976                    }
     4977
     4978                    cntSpawned = spawnedMachines.size();
     4979                    LogFlowFunc (("UPDATE: spawned session count = %d\n", cntSpawned));
    49454980                }
    49464981            }
     
    49544989        ::DosCloseMuxWaitSem (muxSem);
    49554990
    4956     /* delete the set of opened machines if any */
     4991    /* release sets of machines if any */
    49574992    machines.clear();
     4993    spawnedMachines.clear();
    49584994
    49594995#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
     
    49835019                break;
    49845020
    4985             if (VBOX_SUCCESS (rc) || update)
     5021            if (VBOX_SUCCESS (rc) || update || updateSpawned)
    49865022            {
    49875023                /* VBOX_SUCCESS (rc) means an update event is signaled */
    49885024
    4989                 /* obtain a new set of opened machines */
    4990                 that->getOpenedMachines (machines);
    4991                 cnt = machines.size();
    4992                 LogFlowFunc (("UPDATE: direct session count = %d\n", cnt));
    4993             }
    4994 
    4995             if (VBOX_SUCCESS (rc) || updateSpawned)
    4996             {
    4997                 /* VBOX_SUCCESS (rc) means an update event is signaled */
    4998 
    4999                 /* obtain a new set of spawned machines */
    5000                 that->getSpawnedMachines (spawnedMachines);
    5001                 cntSpawned = spawnedMachines.size();
    5002                 LogFlowFunc (("UPDATE: spawned session count = %d\n", cntSpawned));
     5025                AutoReadLock thatLock (that);
     5026
     5027                if (VBOX_SUCCESS (rc) || update)
     5028                {
     5029                    /* obtain a new set of opened machines */
     5030                    machines.clear();
     5031
     5032                    for (MachineList::iterator it = that->mData.mMachines.begin();
     5033                         it != that->mData.mMachines.end(); ++ it)
     5034                    {
     5035                        ComObjPtr <SessionMachine> sm;
     5036                        if ((*it)->isSessionOpen (sm))
     5037                            machines.push_back (sm);
     5038                    }
     5039
     5040                    cnt = machines.size();
     5041                    LogFlowFunc (("UPDATE: direct session count = %d\n", cnt));
     5042                }
     5043
     5044                if (VBOX_SUCCESS (rc) || updateSpawned)
     5045                {
     5046                    /* obtain a new set of spawned machines */
     5047                    spawnedMachines.clear();
     5048
     5049                    for (MachineList::iterator it = that->mData.mMachines.begin();
     5050                         it != that->mData.mMachines.end(); ++ it)
     5051                    {
     5052                        if ((*it)->isSessionSpawning())
     5053                            spawnedMachines.push_back (*it);
     5054                    }
     5055
     5056                    cntSpawned = spawnedMachines.size();
     5057                    LogFlowFunc (("UPDATE: spawned session count = %d\n", cntSpawned));
     5058                }
    50035059            }
    50045060
     
    50545110    while (0);
    50555111
    5056     /* delete the set of opened machines if any */
     5112    /* release sets of machines if any */
    50575113    machines.clear();
     5114    spawnedMachines.clear();
    50585115
    50595116#else
  • trunk/src/VBox/Main/include/MachineImpl.h

    r13436 r13457  
    560560    bool isRegistered() { return !!mData->mRegistered; }
    561561
    562     ComObjPtr <SessionMachine> sessionMachine();
    563 
    564     bool checkForSpawnFailure();
    565 
    566562    /**
    567563     *  Returns the VirtualBox object this machine belongs to.
     
    626622                               Progress *aProgress);
    627623    HRESULT openExistingSession (IInternalSessionControl *aControl);
     624
     625#if defined (RT_OS_WINDOWS)
     626    bool isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     627                        HANDLE *aIPCSem = NULL);
     628    bool isSessionSpawning (RTPROCESS *aPID = NULL);
     629#elif defined (RT_OS_OS2)
     630    bool isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     631                        HMTX *aIPCSem = NULL);
     632    bool isSessionSpawning (RTPROCESS *aPID = NULL);
     633#else
     634    bool isSessionOpen (ComObjPtr <SessionMachine> &aMachine);
     635    bool isSessionSpawning();
     636#endif
     637
     638    bool checkForSpawnFailure();
    628639
    629640    HRESULT trySetRegistered (BOOL aRegistered);
     
    859870
    860871    bool checkForDeath();
    861     bool checkForSpawnFailure();
    862 
    863 #if defined (RT_OS_WINDOWS)
    864     HANDLE ipcSem() { return mIPCSem; }
    865 #elif defined (RT_OS_OS2)
    866     HMTX ipcSem() { return mIPCSem; }
    867 #endif
    868872
    869873    HRESULT onDVDDriveChange();
     
    930934    SnapshotData mSnapshotData;
    931935
    932     /** interprocess semaphore handle (id) for this machine */
    933 #if defined(RT_OS_WINDOWS)
     936    /** interprocess semaphore handle for this machine */
     937#if defined (RT_OS_WINDOWS)
    934938    HANDLE mIPCSem;
    935939    Bstr mIPCSemName;
    936 #elif defined(RT_OS_OS2)
     940    friend bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     941                                        HANDLE *aIPCSem);
     942#elif defined (RT_OS_OS2)
    937943    HMTX mIPCSem;
    938944    Bstr mIPCSemName;
    939 #elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
     945    friend bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     946                                        HMTX *aIPCSem);
     947#elif defined (VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
    940948    int mIPCSem;
    941949#else
  • trunk/src/VBox/Main/include/VirtualBoxImpl.h

    r13436 r13457  
    8383    typedef std::list <ComPtr <IVirtualBoxCallback> > CallbackList;
    8484    typedef std::vector <ComPtr <IVirtualBoxCallback> > CallbackVector;
     85
     86    typedef std::vector <ComObjPtr <SessionMachine> > SessionMachineVector;
     87    typedef std::vector <ComObjPtr <Machine> > MachineVector;
    8588
    8689    class CallbackEvent;
     
    231234    ComObjPtr <GuestOSType> getUnknownOSType();
    232235
    233     typedef std::vector <ComObjPtr <SessionMachine> > SessionMachineVector;
    234     typedef std::vector <ComObjPtr <Machine> > MachineVector;
    235236    void getOpenedMachines (SessionMachineVector &aVector);
    236     void getSpawnedMachines (MachineVector &aVector);
    237237
    238238    bool isMachineIdValid (const Guid &aId)
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