ClientWatcher.cpp revision cc9b22310b11782c8ec2db965d2233156ddb679d
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/** @file
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * VirtualBox API client session crash watcher
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Copyright (C) 2006-2013 Oracle Corporation
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * This file is part of VirtualBox Open Source Edition (OSE), as
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * available from http://www.virtualbox.org. This file is free software;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * you can redistribute it and/or modify it under the terms of the GNU
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * General Public License (GPL) as published by the Free Software
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Foundation, in version 2 as it comes in the "COPYING" file of the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <iprt/asm.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <iprt/assert.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <iprt/log.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <iprt/semaphore.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <iprt/process.h>
a862df29af145cac620492c4ebe1f42c1906c66eSriharsha Basavapatna
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <VBox/com/defs.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <vector>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include "VirtualBoxBase.h"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include "AutoCaller.h"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include "ClientWatcher.h"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include "ClientToken.h"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include "VirtualBoxImpl.h"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include "MachineImpl.h"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#if defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) || defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/** Table for adaptive timeouts. After an update the counter starts at the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * maximum value and decreases to 0, i.e. first the short timeouts are used
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and then the longer ones. This minimizes the detection latency in the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * cases where a change is expected, for crashes. */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic const RTMSINTERVAL s_aUpdateTimeoutSteps[] = { 500, 200, 100, 50, 20, 10, 5 };
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoVirtualBox::ClientWatcher::ClientWatcher() :
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mLock(LOCKCLASS_OBJECTSTATE)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo AssertReleaseFailed();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoVirtualBox::ClientWatcher::~ClientWatcher()
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (mThread != NIL_RTTHREAD)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* signal the client watcher thread, should be exiting now */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb update();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* wait for termination */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RTThreadWait(mThread, RT_INDEFINITE_WAIT, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mThread = NIL_RTTHREAD;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mProcesses.clear();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#if defined(RT_OS_WINDOWS)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (mUpdateReq != NULL)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ::CloseHandle(mUpdateReq);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mUpdateReq = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan#elif defined(RT_OS_OS2) || defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) || defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (mUpdateReq != NIL_RTSEMEVENT)
19b65a69adc64b3289ccb2fc32b805782e3f4540sb {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram RTSemEventDestroy(mUpdateReq);
c1c61f44e88f4c8c155272ee56d868043146096asb mUpdateReq = NIL_RTSEMEVENT;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#else
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo# error "Port me!"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANGVirtualBox::ClientWatcher::ClientWatcher(const ComObjPtr<VirtualBox> &pVirtualBox) :
34683adecebe88ca2c857e28be4749f3a083f9fcsg mVirtualBox(pVirtualBox),
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mThread(NIL_RTTHREAD),
34b64c01c6a2242177691e1420a386e2789f79dcWENTAO YANG mUpdateReq(CWUPDATEREQARG),
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mLock(LOCKCLASS_OBJECTSTATE)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
34683adecebe88ca2c857e28be4749f3a083f9fcsg#if defined(RT_OS_WINDOWS)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mUpdateReq = ::CreateEvent(NULL, FALSE, FALSE, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#elif defined(RT_OS_OS2)
34683adecebe88ca2c857e28be4749f3a083f9fcsg RTSemEventCreate(&mUpdateReq);
19b65a69adc64b3289ccb2fc32b805782e3f4540sb#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER) || defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
c1c61f44e88f4c8c155272ee56d868043146096asb RTSemEventCreate(&mUpdateReq);
c1c61f44e88f4c8c155272ee56d868043146096asb /* start with high timeouts, nothing to do */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASMAtomicUoWriteU8(&mUpdateAdaptCtr, 0);
c1c61f44e88f4c8c155272ee56d868043146096asb#else
bce0a86e5d4d65341c5aca6da2595c848297b2aaWENTAO YANG# error "Port me!"
bce0a86e5d4d65341c5aca6da2595c848297b2aaWENTAO YANG#endif
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb int vrc = RTThreadCreate(&mThread,
f0ca1d9a12d54d304791bc74525e2010ca924726sb worker,
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void *)this,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna 0,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna RTTHREADTYPE_MAIN_WORKER,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna RTTHREADFLAGS_WAITABLE,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna "Watcher");
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna AssertRC(vrc);
bce0a86e5d4d65341c5aca6da2595c848297b2aaWENTAO YANG}
bce0a86e5d4d65341c5aca6da2595c848297b2aaWENTAO YANG
34683adecebe88ca2c857e28be4749f3a083f9fcsgbool VirtualBox::ClientWatcher::isReady()
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return mThread != NIL_RTTHREAD;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/**
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Sends a signal to the thread to rescan the clients/VMs having open sessions.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvoid VirtualBox::ClientWatcher::update()
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram AssertReturnVoid(mThread != NIL_RTTHREAD);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* sent an update request */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#if defined(RT_OS_WINDOWS)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ::SetEvent(mUpdateReq);
d8a518c84b0b033745c344594c3478e1294f3a9aSriharsha Basavapatna#elif defined(RT_OS_OS2)
f0ca1d9a12d54d304791bc74525e2010ca924726sb RTSemEventSignal(mUpdateReq);
f0ca1d9a12d54d304791bc74525e2010ca924726sb#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* use short timeouts, as we expect changes */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASMAtomicUoWriteU8(&mUpdateAdaptCtr, RT_ELEMENTS(s_aUpdateTimeoutSteps) - 1);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram RTSemEventSignal(mUpdateReq);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram RTSemEventSignal(mUpdateReq);
808f26a819b6259a3340d8d53074a2f1635315cbSriharsha Basavapatna#else
808f26a819b6259a3340d8d53074a2f1635315cbSriharsha Basavapatna# error "Port me!"
808f26a819b6259a3340d8d53074a2f1635315cbSriharsha Basavapatna#endif
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
7a327842c3ad1ec3b602c454b218df4ebbc716fbwentaoy
7a327842c3ad1ec3b602c454b218df4ebbc716fbwentaoy/**
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Adds a process to the list of processes to be reaped. This call should be
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * followed by a call to update() to cause the necessary actions immediately,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * in case the process crashes straight away.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANGvoid VirtualBox::ClientWatcher::addProcess(RTPROCESS pid)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram AssertReturnVoid(mThread != NIL_RTTHREAD);
c1c61f44e88f4c8c155272ee56d868043146096asb /* @todo r=klaus, do the reaping on all platforms! */
c1c61f44e88f4c8c155272ee56d868043146096asb#ifndef RT_OS_WINDOWS
c1c61f44e88f4c8c155272ee56d868043146096asb AutoWriteLock alock(mLock COMMA_LOCKVAL_SRC_POS);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mProcesses.push_back(pid);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#endif
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/**
d8a518c84b0b033745c344594c3478e1294f3a9aSriharsha Basavapatna * Thread worker function that watches the termination of all client processes
c1c61f44e88f4c8c155272ee56d868043146096asb * that have open sessions using IMachine::LockMachine()
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb/*static*/
c1c61f44e88f4c8c155272ee56d868043146096asbDECLCALLBACK(int) VirtualBox::ClientWatcher::worker(RTTHREAD /* thread */, void *pvUser)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb LogFlowFuncEnter();
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb VirtualBox::ClientWatcher *that = (VirtualBox::ClientWatcher *)pvUser;
678453a8ed49104d8adad58f3ba591bdc39883e8speer Assert(that);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng typedef std::vector<ComObjPtr<Machine> > MachineVector;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng typedef std::vector<ComObjPtr<SessionMachine> > SessionMachineVector;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng SessionMachineVector machines;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng MachineVector spawnedMachines;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng size_t cnt = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng size_t cntSpawned = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna VirtualBoxBase::initializeComForThread();
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#if defined(RT_OS_WINDOWS)
bce0a86e5d4d65341c5aca6da2595c848297b2aaWENTAO YANG
bce0a86e5d4d65341c5aca6da2595c848297b2aaWENTAO YANG /// @todo (dmik) processes reaping!
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
06db247c678f0e3956535e8a6dec31d6c2108827raghuram HANDLE handles[MAXIMUM_WAIT_OBJECTS];
06db247c678f0e3956535e8a6dec31d6c2108827raghuram handles[0] = that->mUpdateReq;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
445b4c2ed2d52ef648ae6b36e4f5e14ff3d234afsb do
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
19b65a69adc64b3289ccb2fc32b805782e3f4540sb AutoCaller autoCaller(that->mVirtualBox);
0e8b4070e8262256f51dbb1aae9d22fa2f1366fcsb /* VirtualBox has been early uninitialized, terminate */
0e8b4070e8262256f51dbb1aae9d22fa2f1366fcsb if (!autoCaller.isOk())
06db247c678f0e3956535e8a6dec31d6c2108827raghuram break;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG do
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* release the caller to let uninit() ever proceed */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram autoCaller.release();
34b64c01c6a2242177691e1420a386e2789f79dcWENTAO YANG
34b64c01c6a2242177691e1420a386e2789f79dcWENTAO YANG DWORD rc = ::WaitForMultipleObjects((DWORD)(1 + cnt + cntSpawned),
06db247c678f0e3956535e8a6dec31d6c2108827raghuram handles,
c1c61f44e88f4c8c155272ee56d868043146096asb FALSE,
c1c61f44e88f4c8c155272ee56d868043146096asb INFINITE);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* Restore the caller before using VirtualBox. If it fails, this
c1c61f44e88f4c8c155272ee56d868043146096asb * means VirtualBox is being uninitialized and we must terminate. */
c1c61f44e88f4c8c155272ee56d868043146096asb autoCaller.add();
c1c61f44e88f4c8c155272ee56d868043146096asb if (!autoCaller.isOk())
c1c61f44e88f4c8c155272ee56d868043146096asb break;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb bool update = false;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (rc == WAIT_OBJECT_0)
c1c61f44e88f4c8c155272ee56d868043146096asb {
c1c61f44e88f4c8c155272ee56d868043146096asb /* update event is signaled */
c1c61f44e88f4c8c155272ee56d868043146096asb update = true;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb else if (rc > WAIT_OBJECT_0 && rc <= (WAIT_OBJECT_0 + cnt))
f0ca1d9a12d54d304791bc74525e2010ca924726sb {
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* machine mutex is released */
f0ca1d9a12d54d304791bc74525e2010ca924726sb (machines[rc - WAIT_OBJECT_0 - 1])->checkForDeath();
f0ca1d9a12d54d304791bc74525e2010ca924726sb update = true;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb else if (rc > WAIT_ABANDONED_0 && rc <= (WAIT_ABANDONED_0 + cnt))
f0ca1d9a12d54d304791bc74525e2010ca924726sb {
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* machine mutex is abandoned due to client process termination */
f0ca1d9a12d54d304791bc74525e2010ca924726sb (machines[rc - WAIT_ABANDONED_0 - 1])->checkForDeath();
f0ca1d9a12d54d304791bc74525e2010ca924726sb update = true;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb else if (rc > WAIT_OBJECT_0 + cnt && rc <= (WAIT_OBJECT_0 + cntSpawned))
f0ca1d9a12d54d304791bc74525e2010ca924726sb {
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* spawned VM process has terminated (normally or abnormally) */
f0ca1d9a12d54d304791bc74525e2010ca924726sb (spawnedMachines[rc - WAIT_OBJECT_0 - cnt - 1])->
f0ca1d9a12d54d304791bc74525e2010ca924726sb checkForSpawnFailure();
f0ca1d9a12d54d304791bc74525e2010ca924726sb update = true;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (update)
f0ca1d9a12d54d304791bc74525e2010ca924726sb {
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* close old process handles */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (size_t i = 1 + cnt; i < 1 + cnt + cntSpawned; ++i)
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb CloseHandle(handles[i]);
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb // get reference to the machines list in VirtualBox
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb VirtualBox::MachinesOList &allMachines = that->mVirtualBox->getMachinesList();
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb // lock the machines list for reading
51aa9d07dcd9c8ed955768d19058f8c15460fd7csb AutoReadLock thatLock(allMachines.getLockHandle() COMMA_LOCKVAL_SRC_POS);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* obtain a new set of opened machines */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna cnt = 0;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna machines.clear();
678453a8ed49104d8adad58f3ba591bdc39883e8speer
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna for (MachinesOList::iterator it = allMachines.begin();
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna it != allMachines.end();
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ++it)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /// @todo handle situations with more than 64 objects
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna AssertMsgBreak((1 + cnt) <= MAXIMUM_WAIT_OBJECTS,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ("MAXIMUM_WAIT_OBJECTS reached"));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ComObjPtr<SessionMachine> sm;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if ((*it)->isSessionOpenOrClosing(sm))
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna AutoCaller smCaller(sm);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (smCaller.isOk())
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna AutoReadLock smLock(sm COMMA_LOCKVAL_SRC_POS);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna Machine::ClientToken *ct = sm->getClientToken();
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (ct)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna HANDLE ipcSem = ct->getToken();
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna machines.push_back(sm);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna handles[1 + cnt] = ipcSem;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ++cnt;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna }
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna }
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna }
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna }
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna LogFlowFunc(("UPDATE: direct session count = %d\n", cnt));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* obtain a new set of spawned machines */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna cntSpawned = 0;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna spawnedMachines.clear();
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna for (MachinesOList::iterator it = allMachines.begin();
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna it != allMachines.end();
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ++it)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /// @todo handle situations with more than 64 objects
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna AssertMsgBreak((1 + cnt + cntSpawned) <= MAXIMUM_WAIT_OBJECTS,
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ("MAXIMUM_WAIT_OBJECTS reached"));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if ((*it)->isSessionSpawning())
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna {
34f94fbc7a730740933e4776ade5f74009afe4ceWENTAO YANG ULONG pid;
34f94fbc7a730740933e4776ade5f74009afe4ceWENTAO YANG HRESULT hrc = (*it)->COMGETTER(SessionPID)(&pid);
34f94fbc7a730740933e4776ade5f74009afe4ceWENTAO YANG if (SUCCEEDED(hrc))
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna HANDLE ph = OpenProcess(SYNCHRONIZE, FALSE, pid);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna AssertMsg(ph != NULL, ("OpenProcess (pid=%d) failed with %d\n",
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna pid, GetLastError()));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna if (ph != NULL)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna {
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna spawnedMachines.push_back(*it);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna handles[1 + cnt + cntSpawned] = ph;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna ++cntSpawned;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna }
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna }
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna }
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna }
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna LogFlowFunc(("UPDATE: spawned session count = %d\n", cntSpawned));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna // machines lock unwinds here
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna }
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna }
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna while (true);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna }
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna while (0);
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* close old process handles */
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna for (size_t i = 1 + cnt; i < 1 + cnt + cntSpawned; ++i)
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna CloseHandle(handles[i]);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* release sets of machines if any */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram machines.clear();
06db247c678f0e3956535e8a6dec31d6c2108827raghuram spawnedMachines.clear();
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ::CoUninitialize();
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna#elif defined(RT_OS_OS2)
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /// @todo (dmik) processes reaping!
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna /* according to PMREF, 64 is the maximum for the muxwait list */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram SEMRECORD handles[64];
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna HMUX muxSem = NULLHANDLE;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna do
06db247c678f0e3956535e8a6dec31d6c2108827raghuram {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram AutoCaller autoCaller(that->mVirtualBox);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* VirtualBox has been early uninitialized, terminate */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (!autoCaller.isOk())
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna break;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna do
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* release the caller to let uninit() ever proceed */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna autoCaller.release();
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna int vrc = RTSemEventWait(that->mUpdateReq, 500);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* Restore the caller before using VirtualBox. If it fails, this
f0ca1d9a12d54d304791bc74525e2010ca924726sb * means VirtualBox is being uninitialized and we must terminate. */
f0ca1d9a12d54d304791bc74525e2010ca924726sb autoCaller.add();
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (!autoCaller.isOk())
f0ca1d9a12d54d304791bc74525e2010ca924726sb break;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna
f0ca1d9a12d54d304791bc74525e2010ca924726sb bool update = false;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram bool updateSpawned = false;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (RT_SUCCESS(vrc))
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb {
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* update event is signaled */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb update = true;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb updateSpawned = true;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb }
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb else
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb {
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb AssertMsg(vrc == VERR_TIMEOUT || vrc == VERR_INTERRUPTED,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ("RTSemEventWait returned %Rrc\n", vrc));
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* are there any mutexes? */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (cnt > 0)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* figure out what's going on with machines */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo unsigned long semId = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo APIRET arc = ::DosWaitMuxWaitSem(muxSem,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo SEM_IMMEDIATE_RETURN, &semId);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (arc == NO_ERROR)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* machine mutex is normally released */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo Assert(semId >= 0 && semId < cnt);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (semId >= 0 && semId < cnt)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#if 0//def DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo AutoReadLock machineLock(machines[semId] COMMA_LOCKVAL_SRC_POS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LogFlowFunc(("released mutex: machine='%ls'\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo machines[semId]->name().raw()));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo machines[semId]->checkForDeath();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo update = true;
71184a4009bd4b0be64a3ad8c1013f581fa0e021WENTAO YANG }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo else if (arc == ERROR_SEM_OWNER_DIED)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* machine mutex is abandoned due to client process
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * termination; find which mutex is in the Owner Died
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * state */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (size_t i = 0; i < cnt; ++i)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo PID pid; TID tid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo unsigned long reqCnt;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo arc = DosQueryMutexSem((HMTX)handles[i].hsemCur, &pid, &tid, &reqCnt);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (arc == ERROR_SEM_OWNER_DIED)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* close the dead mutex as asked by PMREF */
205eeb1ae627fcf67b5705c443a2b56a8263406blm ::DosCloseMutexSem((HMTX)handles[i].hsemCur);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo Assert(i >= 0 && i < cnt);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (i >= 0 && i < cnt)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#if 0//def DEBUG
06db247c678f0e3956535e8a6dec31d6c2108827raghuram {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo AutoReadLock machineLock(machines[semId] COMMA_LOCKVAL_SRC_POS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LogFlowFunc(("mutex owner dead: machine='%ls'\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo machines[i]->name().raw()));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo machines[i]->checkForDeath();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo update = true;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo else
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo AssertMsg(arc == ERROR_INTERRUPT || arc == ERROR_TIMEOUT,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ("DosWaitMuxWaitSem returned %d\n", arc));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* are there any spawning sessions? */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (cntSpawned > 0)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (size_t i = 0; i < cntSpawned; ++i)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo updateSpawned |= (spawnedMachines[i])->
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo checkForSpawnFailure();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (update || updateSpawned)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo // get reference to the machines list in VirtualBox
f0ca1d9a12d54d304791bc74525e2010ca924726sb VirtualBox::MachinesOList &allMachines = that->mVirtualBox->getMachinesList();
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb // lock the machines list for reading
c1c61f44e88f4c8c155272ee56d868043146096asb AutoReadLock thatLock(allMachines.getLockHandle() COMMA_LOCKVAL_SRC_POS);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (update)
678453a8ed49104d8adad58f3ba591bdc39883e8speer {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* close the old muxsem */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (muxSem != NULLHANDLE)
bce0a86e5d4d65341c5aca6da2595c848297b2aaWENTAO YANG ::DosCloseMuxWaitSem(muxSem);
bce0a86e5d4d65341c5aca6da2595c848297b2aaWENTAO YANG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* obtain a new set of opened machines */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cnt = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo machines.clear();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (MachinesOList::iterator it = allMachines.begin();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo it != allMachines.end(); ++it)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /// @todo handle situations with more than 64 objects
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo AssertMsg(cnt <= 64 /* according to PMREF */,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ("maximum of 64 mutex semaphores reached (%d)",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cnt));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ComObjPtr<SessionMachine> sm;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((*it)->isSessionOpenOrClosing(sm))
34683adecebe88ca2c857e28be4749f3a083f9fcsg {
34683adecebe88ca2c857e28be4749f3a083f9fcsg AutoCaller smCaller(sm);
34683adecebe88ca2c857e28be4749f3a083f9fcsg if (smCaller.isOk())
34683adecebe88ca2c857e28be4749f3a083f9fcsg {
34683adecebe88ca2c857e28be4749f3a083f9fcsg AutoReadLock smLock(sm COMMA_LOCKVAL_SRC_POS);
34683adecebe88ca2c857e28be4749f3a083f9fcsg ClientToken *ct = sm->getClientToken();
34683adecebe88ca2c857e28be4749f3a083f9fcsg if (ct)
34683adecebe88ca2c857e28be4749f3a083f9fcsg {
34683adecebe88ca2c857e28be4749f3a083f9fcsg HMTX ipcSem = ct->getToken();
34683adecebe88ca2c857e28be4749f3a083f9fcsg machines.push_back(sm);
34683adecebe88ca2c857e28be4749f3a083f9fcsg handles[cnt].hsemCur = (HSEM)ipcSem;
34683adecebe88ca2c857e28be4749f3a083f9fcsg handles[cnt].ulUser = cnt;
34683adecebe88ca2c857e28be4749f3a083f9fcsg ++cnt;
34683adecebe88ca2c857e28be4749f3a083f9fcsg }
34683adecebe88ca2c857e28be4749f3a083f9fcsg }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LogFlowFunc(("UPDATE: direct session count = %d\n", cnt));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (cnt > 0)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* create a new muxsem */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo APIRET arc = ::DosCreateMuxWaitSem(NULL, &muxSem, cnt,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo handles,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DCMW_WAIT_ANY);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo AssertMsg(arc == NO_ERROR,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ("DosCreateMuxWaitSem returned %d\n", arc));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo NOREF(arc);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (updateSpawned)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* obtain a new set of spawned machines */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo spawnedMachines.clear();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (MachinesOList::iterator it = allMachines.begin();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo it != allMachines.end(); ++it)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((*it)->isSessionSpawning())
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo spawnedMachines.push_back(*it);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cntSpawned = spawnedMachines.size();
06db247c678f0e3956535e8a6dec31d6c2108827raghuram LogFlowFunc(("UPDATE: spawned session count = %d\n", cntSpawned));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo while (true);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo while (0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* close the muxsem */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (muxSem != NULLHANDLE)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ::DosCloseMuxWaitSem(muxSem);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* release sets of machines if any */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo machines.clear();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo spawnedMachines.clear();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#elif defined(VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bool update = false;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bool updateSpawned = false;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo do
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo AutoCaller autoCaller(that->mVirtualBox);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!autoCaller.isOk())
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo do
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* release the caller to let uninit() ever proceed */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo autoCaller.release();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* determine wait timeout adaptively: after updating information
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * relevant to the client watcher, check a few times more
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * frequently. This ensures good reaction time when the signalling
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * has to be done a bit before the actual change for technical
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * reasons, and saves CPU cycles when no activities are expected. */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RTMSINTERVAL cMillies;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint8_t uOld, uNew;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo do
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uOld = ASMAtomicUoReadU8(&that->mUpdateAdaptCtr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uNew = uOld ? uOld - 1 : uOld;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } while (!ASMAtomicCmpXchgU8(&that->mUpdateAdaptCtr, uNew, uOld));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo Assert(uOld <= RT_ELEMENTS(s_aUpdateTimeoutSteps) - 1);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cMillies = s_aUpdateTimeoutSteps[uOld];
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rc = RTSemEventWait(that->mUpdateReq, cMillies);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Restore the caller before using VirtualBox. If it fails, this
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * means VirtualBox is being uninitialized and we must terminate.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo autoCaller.add();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!autoCaller.isOk())
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (RT_SUCCESS(rc) || update || updateSpawned)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* RT_SUCCESS(rc) means an update event is signaled */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo // get reference to the machines list in VirtualBox
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VirtualBox::MachinesOList &allMachines = that->mVirtualBox->getMachinesList();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo // lock the machines list for reading
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo AutoReadLock thatLock(allMachines.getLockHandle() COMMA_LOCKVAL_SRC_POS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG if (RT_SUCCESS(rc) || update)
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG /* obtain a new set of opened machines */
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG machines.clear();
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG for (MachinesOList::iterator it = allMachines.begin();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo it != allMachines.end();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ++it)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ComObjPtr<SessionMachine> sm;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((*it)->isSessionOpenOrClosing(sm))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo machines.push_back(sm);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cnt = machines.size();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LogFlowFunc(("UPDATE: direct session count = %d\n", cnt));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (RT_SUCCESS(rc) || updateSpawned)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* obtain a new set of spawned machines */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo spawnedMachines.clear();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (MachinesOList::iterator it = allMachines.begin();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo it != allMachines.end();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ++it)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((*it)->isSessionSpawning())
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo spawnedMachines.push_back(*it);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cntSpawned = spawnedMachines.size();
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna LogFlowFunc(("UPDATE: spawned session count = %d\n", cntSpawned));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng // machines lock unwinds here
19b65a69adc64b3289ccb2fc32b805782e3f4540sb }
808f26a819b6259a3340d8d53074a2f1635315cbSriharsha Basavapatna
808f26a819b6259a3340d8d53074a2f1635315cbSriharsha Basavapatna update = false;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (size_t i = 0; i < cnt; ++i)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo update |= (machines[i])->checkForDeath();
19b65a69adc64b3289ccb2fc32b805782e3f4540sb
19b65a69adc64b3289ccb2fc32b805782e3f4540sb updateSpawned = false;
19b65a69adc64b3289ccb2fc32b805782e3f4540sb for (size_t i = 0; i < cntSpawned; ++i)
19b65a69adc64b3289ccb2fc32b805782e3f4540sb updateSpawned |= (spawnedMachines[i])->checkForSpawnFailure();
19b65a69adc64b3289ccb2fc32b805782e3f4540sb
19b65a69adc64b3289ccb2fc32b805782e3f4540sb /* reap child processes */
19b65a69adc64b3289ccb2fc32b805782e3f4540sb {
19b65a69adc64b3289ccb2fc32b805782e3f4540sb AutoWriteLock alock(that->mLock COMMA_LOCKVAL_SRC_POS);
19b65a69adc64b3289ccb2fc32b805782e3f4540sb if (that->mProcesses.size())
19b65a69adc64b3289ccb2fc32b805782e3f4540sb {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LogFlowFunc(("UPDATE: child process count = %d\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo that->mProcesses.size()));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VirtualBox::ClientWatcher::ProcessList::iterator it = that->mProcesses.begin();
205eeb1ae627fcf67b5705c443a2b56a8263406blm while (it != that->mProcesses.end())
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
c1c61f44e88f4c8c155272ee56d868043146096asb RTPROCESS pid = *it;
c1c61f44e88f4c8c155272ee56d868043146096asb RTPROCSTATUS status;
205eeb1ae627fcf67b5705c443a2b56a8263406blm int vrc = ::RTProcWait(pid, RTPROCWAIT_FLAGS_NOBLOCK, &status);
c1c61f44e88f4c8c155272ee56d868043146096asb if (vrc == VINF_SUCCESS)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ( status.enmReason != RTPROCEXITREASON_NORMAL
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo || status.iStatus != RTEXITCODE_SUCCESS)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
205eeb1ae627fcf67b5705c443a2b56a8263406blm switch (status.enmReason)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
c1c61f44e88f4c8c155272ee56d868043146096asb default:
205eeb1ae627fcf67b5705c443a2b56a8263406blm case RTPROCEXITREASON_NORMAL:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LogRel(("Reaper: Pid %d (%x) exited normally: %d (%#x)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo pid, pid, status.iStatus, status.iStatus));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case RTPROCEXITREASON_ABEND:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LogRel(("Reaper: Pid %d (%x) abended: %d (%#x)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo pid, pid, status.iStatus, status.iStatus));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna case RTPROCEXITREASON_SIGNAL:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LogRel(("Reaper: Pid %d (%x) was signalled: %d (%#x)\n",
205eeb1ae627fcf67b5705c443a2b56a8263406blm pid, pid, status.iStatus, status.iStatus));
34683adecebe88ca2c857e28be4749f3a083f9fcsg break;
205eeb1ae627fcf67b5705c443a2b56a8263406blm }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo else
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LogFlowFunc(("pid %d (%x) was reaped, status=%d, reason=%d\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo pid, pid, status.iStatus,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status.enmReason));
7bd3a2e26cc8569257b88c1691d559138e1d32d0Sriharsha Basavapatna it = that->mProcesses.erase(it);
34b64c01c6a2242177691e1420a386e2789f79dcWENTAO YANG }
34b64c01c6a2242177691e1420a386e2789f79dcWENTAO YANG else
34b64c01c6a2242177691e1420a386e2789f79dcWENTAO YANG {
34b64c01c6a2242177691e1420a386e2789f79dcWENTAO YANG LogFlowFunc(("pid %d (%x) was NOT reaped, vrc=%Rrc\n",
34b64c01c6a2242177691e1420a386e2789f79dcWENTAO YANG pid, pid, vrc));
34b64c01c6a2242177691e1420a386e2789f79dcWENTAO YANG if (vrc != VERR_PROCESS_RUNNING)
34b64c01c6a2242177691e1420a386e2789f79dcWENTAO YANG {
34b64c01c6a2242177691e1420a386e2789f79dcWENTAO YANG /* remove the process if it is not already running */
34b64c01c6a2242177691e1420a386e2789f79dcWENTAO YANG it = that->mProcesses.erase(it);
34b64c01c6a2242177691e1420a386e2789f79dcWENTAO YANG }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan else
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ++it;
205eeb1ae627fcf67b5705c443a2b56a8263406blm }
34683adecebe88ca2c857e28be4749f3a083f9fcsg }
205eeb1ae627fcf67b5705c443a2b56a8263406blm }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
7a327842c3ad1ec3b602c454b218df4ebbc716fbwentaoy while (true);
7a327842c3ad1ec3b602c454b218df4ebbc716fbwentaoy }
7a327842c3ad1ec3b602c454b218df4ebbc716fbwentaoy while (0);
7a327842c3ad1ec3b602c454b218df4ebbc716fbwentaoy
7a327842c3ad1ec3b602c454b218df4ebbc716fbwentaoy /* release sets of machines if any */
7a327842c3ad1ec3b602c454b218df4ebbc716fbwentaoy machines.clear();
19b65a69adc64b3289ccb2fc32b805782e3f4540sb spawnedMachines.clear();
808f26a819b6259a3340d8d53074a2f1635315cbSriharsha Basavapatna
808f26a819b6259a3340d8d53074a2f1635315cbSriharsha Basavapatna#elif defined(VBOX_WITH_GENERIC_SESSION_WATCHER)
808f26a819b6259a3340d8d53074a2f1635315cbSriharsha Basavapatna
19b65a69adc64b3289ccb2fc32b805782e3f4540sb bool updateSpawned = false;
808f26a819b6259a3340d8d53074a2f1635315cbSriharsha Basavapatna
808f26a819b6259a3340d8d53074a2f1635315cbSriharsha Basavapatna do
808f26a819b6259a3340d8d53074a2f1635315cbSriharsha Basavapatna {
808f26a819b6259a3340d8d53074a2f1635315cbSriharsha Basavapatna AutoCaller autoCaller(that->mVirtualBox);
19b65a69adc64b3289ccb2fc32b805782e3f4540sb if (!autoCaller.isOk())
19b65a69adc64b3289ccb2fc32b805782e3f4540sb break;
19b65a69adc64b3289ccb2fc32b805782e3f4540sb
19b65a69adc64b3289ccb2fc32b805782e3f4540sb do
19b65a69adc64b3289ccb2fc32b805782e3f4540sb {
19b65a69adc64b3289ccb2fc32b805782e3f4540sb /* release the caller to let uninit() ever proceed */
19b65a69adc64b3289ccb2fc32b805782e3f4540sb autoCaller.release();
19b65a69adc64b3289ccb2fc32b805782e3f4540sb
19b65a69adc64b3289ccb2fc32b805782e3f4540sb /* determine wait timeout adaptively: after updating information
19b65a69adc64b3289ccb2fc32b805782e3f4540sb * relevant to the client watcher, check a few times more
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * frequently. This ensures good reaction time when the signalling
34683adecebe88ca2c857e28be4749f3a083f9fcsg * has to be done a bit before the actual change for technical
34683adecebe88ca2c857e28be4749f3a083f9fcsg * reasons, and saves CPU cycles when no activities are expected. */
34683adecebe88ca2c857e28be4749f3a083f9fcsg RTMSINTERVAL cMillies;
34683adecebe88ca2c857e28be4749f3a083f9fcsg {
34683adecebe88ca2c857e28be4749f3a083f9fcsg uint8_t uOld, uNew;
34683adecebe88ca2c857e28be4749f3a083f9fcsg do
34683adecebe88ca2c857e28be4749f3a083f9fcsg {
34683adecebe88ca2c857e28be4749f3a083f9fcsg uOld = ASMAtomicUoReadU8(&that->mUpdateAdaptCtr);
34683adecebe88ca2c857e28be4749f3a083f9fcsg uNew = uOld ? uOld - 1 : uOld;
34683adecebe88ca2c857e28be4749f3a083f9fcsg } while (!ASMAtomicCmpXchgU8(&that->mUpdateAdaptCtr, uNew, uOld));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo Assert(uOld <= RT_ELEMENTS(s_aUpdateTimeoutSteps) - 1);
19b65a69adc64b3289ccb2fc32b805782e3f4540sb cMillies = s_aUpdateTimeoutSteps[uOld];
19b65a69adc64b3289ccb2fc32b805782e3f4540sb }
34683adecebe88ca2c857e28be4749f3a083f9fcsg
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rc = RTSemEventWait(that->mUpdateReq, cMillies);
19b65a69adc64b3289ccb2fc32b805782e3f4540sb
19b65a69adc64b3289ccb2fc32b805782e3f4540sb /*
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG * Restore the caller before using VirtualBox. If it fails, this
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG * means VirtualBox is being uninitialized and we must terminate.
19b65a69adc64b3289ccb2fc32b805782e3f4540sb */
19b65a69adc64b3289ccb2fc32b805782e3f4540sb autoCaller.add();
19b65a69adc64b3289ccb2fc32b805782e3f4540sb if (!autoCaller.isOk())
19b65a69adc64b3289ccb2fc32b805782e3f4540sb break;
19b65a69adc64b3289ccb2fc32b805782e3f4540sb
19b65a69adc64b3289ccb2fc32b805782e3f4540sb /** @todo this quite big effort for catching machines in spawning
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * state which can't be caught by the token mechanism (as the token
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * can't be in the other process yet) could be eliminated if the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * reaping is made smarter, having cross-reference information
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * from the pid to the corresponding machine object. Both cases do
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * more or less the same thing anyway. */
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG if (RT_SUCCESS(rc) || updateSpawned)
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* RT_SUCCESS(rc) means an update event is signaled */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo // get reference to the machines list in VirtualBox
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VirtualBox::MachinesOList &allMachines = that->mVirtualBox->getMachinesList();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo // lock the machines list for reading
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo AutoReadLock thatLock(allMachines.getLockHandle() COMMA_LOCKVAL_SRC_POS);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (RT_SUCCESS(rc) || updateSpawned)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* obtain a new set of spawned machines */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo spawnedMachines.clear();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (MachinesOList::iterator it = allMachines.begin();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo it != allMachines.end();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ++it)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((*it)->isSessionSpawning())
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo spawnedMachines.push_back(*it);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cntSpawned = spawnedMachines.size();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LogFlowFunc(("UPDATE: spawned session count = %d\n", cntSpawned));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo NOREF(cnt);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo // machines lock unwinds here
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG updateSpawned = false;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG for (size_t i = 0; i < cntSpawned; ++i)
19b65a69adc64b3289ccb2fc32b805782e3f4540sb updateSpawned |= (spawnedMachines[i])->checkForSpawnFailure();
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* reap child processes */
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG AutoWriteLock alock(that->mLock COMMA_LOCKVAL_SRC_POS);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG if (that->mProcesses.size())
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG LogFlowFunc(("UPDATE: child process count = %d\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo that->mProcesses.size()));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VirtualBox::ClientWatcher::ProcessList::iterator it = that->mProcesses.begin();
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG while (it != that->mProcesses.end())
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG RTPROCESS pid = *it;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RTPROCSTATUS status;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG int vrc = ::RTProcWait(pid, RTPROCWAIT_FLAGS_NOBLOCK, &status);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG if (vrc == VINF_SUCCESS)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG if ( status.enmReason != RTPROCEXITREASON_NORMAL
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG || status.iStatus != RTEXITCODE_SUCCESS)
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG switch (status.enmReason)
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG default:
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG case RTPROCEXITREASON_NORMAL:
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG LogRel(("Reaper: Pid %d (%x) exited normally: %d (%#x)\n",
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG pid, pid, status.iStatus, status.iStatus));
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG break;
34683adecebe88ca2c857e28be4749f3a083f9fcsg case RTPROCEXITREASON_ABEND:
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG LogRel(("Reaper: Pid %d (%x) abended: %d (%#x)\n",
5f94e909a253b6d0625c7c7425f59848f0cfb850sg pid, pid, status.iStatus, status.iStatus));
e1ebb9ec908bc2d0a8810f137ebd6566cc8a8061lm break;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG case RTPROCEXITREASON_SIGNAL:
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG LogRel(("Reaper: Pid %d (%x) was signalled: %d (%#x)\n",
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG pid, pid, status.iStatus, status.iStatus));
e1ebb9ec908bc2d0a8810f137ebd6566cc8a8061lm break;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG }
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG }
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG else
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG LogFlowFunc(("pid %d (%x) was reaped, status=%d, reason=%d\n",
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG pid, pid, status.iStatus,
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG status.enmReason));
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG it = that->mProcesses.erase(it);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG }
e1ebb9ec908bc2d0a8810f137ebd6566cc8a8061lm else
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG LogFlowFunc(("pid %d (%x) was NOT reaped, vrc=%Rrc\n",
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG pid, pid, vrc));
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG if (vrc != VERR_PROCESS_RUNNING)
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG /* remove the process if it is not already running */
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG it = that->mProcesses.erase(it);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan else
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG ++it;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG }
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG }
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo while (true);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG }
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG while (0);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG /* release sets of machines if any */
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG machines.clear();
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG spawnedMachines.clear();
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG#else
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG# error "Port me!"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG VirtualBoxBase::uninitializeComForThread();
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG LogFlowFuncLeave();
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG return 0;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG}
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG/* vi: set tabstop=4 shiftwidth=4 expandtab: */
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG