1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/* $Id$ */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** @file
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * VirtualBox Support Service - The Grant Service.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2008-2010 Oracle Corporation
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * available from http://www.virtualbox.org. This file is free software;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * you can redistribute it and/or modify it under the terms of the GNU
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * General Public License (GPL) as published by the Free Software
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * The contents of this file may alternatively be used under the terms
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * of the Common Development and Distribution License Version 1.0
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * VirtualBox OSE distribution, in which case the provisions of the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * CDDL are applicable instead of those of the GPL.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * You may elect to license modified versions of this file under the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * terms and conditions of either the GPL or the CDDL or both.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/*******************************************************************************
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync* Header Files *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync*******************************************************************************/
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#define LOG_GROUP LOG_GROUP_SUP
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include "SUPSvcInternal.h"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <VBox/log.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/asm.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/err.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/assert.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/critsect.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/mem.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/semaphore.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/thread.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/time.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/localipc.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/*******************************************************************************
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync* Structures and Typedefs *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync*******************************************************************************/
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** Pointer to a client instance. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsynctypedef struct SUPSVCGRANTSESSION *PSUPSVCGRANTSESSION;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** Pointer to a Grant service instance. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsynctypedef struct SUPSVCGRANT *PSUPSVCGRANT;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Grant service session data.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsynctypedef struct SUPSVCGRANTSESSION
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Pointer to the next client in the list. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PSUPSVCGRANTSESSION pNext;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Pointer to the previous client in the list. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PSUPSVCGRANTSESSION pPrev;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Pointer to the parent (the service instance). */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PSUPSVCGRANT volatile pParent;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** The local ipc client handle. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLOCALIPCSESSION volatile hSession;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Indicate that the thread should terminate ASAP. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync bool volatile fTerminate;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** The thread handle. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTTHREAD hThread;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync} SUPSVCGRANTSESSION;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * State grant service machine.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsynctypedef enum SUPSVCGRANTSTATE
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** The invalid zero entry. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcGrantState_Invalid = 0,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Creating - the thread is being started.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Next: Paused or Butchered. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcGrantState_Creating,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Paused - the thread is blocked on it's user event semaphore.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Next: Resuming, Terminating or Butchered.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Prev: Creating, Pausing */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcGrantState_Paused,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Resuming - the thread is being unblocked and ushered into RTLocalIpcServiceListen.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Next: Listen or Butchered.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Prev: Paused */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcGrantState_Resuming,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Listen - the thread is in RTLocalIpcServerListen or setting up an incoming session.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Next: Pausing or Butchered.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Prev: Resuming */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcGrantState_Listen,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Pausing - Cancelling the listen and dropping any incoming sessions.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Next: Paused or Butchered.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Prev: Listen */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcGrantState_Pausing,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Butchered - The thread has quit because something when terribly wrong.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Next: Destroyed
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Prev: Any. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcGrantState_Butchered,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Pausing - Cancelling the listen and dropping any incoming sessions.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Next: Destroyed
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Prev: Paused */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcGrantState_Terminating,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Destroyed - the instance is invalid.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Prev: Butchered or Terminating */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcGrantState_Destroyed,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** The end of valid state values. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcGrantState_End,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** The usual 32-bit blowup hack. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcGrantState_32BitHack = 0x7fffffff
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync} SUPSVCGRANTSTATE;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Grant service instance data.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsynctypedef struct SUPSVCGRANT
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** The local ipc server handle. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLOCALIPCSERVER hServer;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Critical section serializing access to the session list, the state,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * the response event, the session event, and the thread event. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCRITSECT CritSect;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** The service thread will signal this event when it has changed to
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * the 'paused' or 'running' state. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTSEMEVENT hResponseEvent;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Event that's signaled on session termination. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTSEMEVENT hSessionEvent;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** The handle to the service thread. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTTHREAD hThread;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Head of the session list. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PSUPSVCGRANTSESSION volatile pSessionHead;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** The service state. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SUPSVCGRANTSTATE volatile enmState;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Critical section serializing access to the SUPR3HardenedVerify APIs. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCRITSECT VerifyCritSect;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync} SUPSVCGRANT;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/*******************************************************************************
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync* Internal Functions *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync*******************************************************************************/
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic const char *supSvcGrantStateName(SUPSVCGRANTSTATE enmState);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Services a client session.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns VINF_SUCCESS.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param hThread The thread handle.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvSession Pointer to the session instance data.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic DECLCALLBACK(int) supSvcGrantSessionThread(RTTHREAD hThread, void *pvSession)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PSUPSVCGRANTSESSION pThis = (PSUPSVCGRANTSESSION)pvSession;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLOCALIPCSESSION hSession = pThis->hSession;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("supSvcGrantSessionThread(%p):\n", pThis));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * Process client requests until it quits or we're cancelled on termination.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync while (!ASMAtomicUoReadBool(&pThis->fTerminate))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTThreadSleep(1000);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** @todo */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Clean up the session.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
c7ff622115966b69b482bd2896662e40d823b22fvboxsync PSUPSVCGRANT pParent = ASMAtomicReadPtrT(&pThis->pParent, PSUPSVCGRANT);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (pParent)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectEnter(&pParent->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("supSvcGrantSessionThread(%p): No parent\n", pThis));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync ASMAtomicXchgHandle(&pThis->hSession, NIL_RTLOCALIPCSESSION, &hSession);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (hSession != NIL_RTLOCALIPCSESSION)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLocalIpcSessionClose(hSession);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("supSvcGrantSessionThread(%p): No session handle\n", pThis));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (pParent)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTSemEventSignal(pParent->hSessionEvent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pParent->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("supSvcGrantSessionThread(%p): exits\n"));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Cleans up a session.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * This is called while inside the grant service critical section.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pThis The session to destroy.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pParent The parent.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic void supSvcGrantSessionDestroy(PSUPSVCGRANTSESSION pThis, PSUPSVCGRANT pParent)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Unlink it.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (pThis->pNext)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Assert(pThis->pNext->pPrev == pThis);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->pNext->pPrev = pThis->pPrev;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (pThis->pPrev)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Assert(pThis->pPrev->pNext == pThis);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->pPrev->pNext = pThis->pNext;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (pParent->pSessionHead == pThis)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pParent->pSessionHead = pThis->pNext;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Free the resources associated with it.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->hThread = NIL_RTTHREAD;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->pNext = NULL;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->pPrev = NULL;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLOCALIPCSESSION hSession;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync ASMAtomicXchgHandle(&pThis->hSession, NIL_RTLOCALIPCSESSION, &hSession);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (hSession != NIL_RTLOCALIPCSESSION)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLocalIpcSessionClose(hSession);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTMemFree(pThis);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Cleans up zombie sessions, locked.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pThis Pointer to the grant service instance data.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic void supSvcGrantCleanUpSessionsLocked(PSUPSVCGRANT pThis)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * Iterate until be make it all the way thru the list.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Only use the thread state as and indicator on whether we can destroy
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * the session or not.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PSUPSVCGRANTSESSION pCur;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync do
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync for (pCur = pThis->pSessionHead; pCur; pCur = pCur->pNext)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = RTThreadWait(pCur->hThread, 0, NULL);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantSessionDestroy(pCur, pThis);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Assert(rc == VERR_TIMEOUT);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Assert(pCur->hThread != NIL_RTTHREAD);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Assert(pCur->pNext != pThis->pSessionHead);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync } while (pCur);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Cleans up zombie sessions.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns VINF_SUCCESS, VBox error code on internal error.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pThis Pointer to the grant service instance data.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param fOwnCritSect Whether we own the crit sect already. The state is preserved.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcGrantCleanUpSessions(PSUPSVCGRANT pThis, bool fOwnCritSect)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = RTCritSectEnter(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantCleanUpSessions: RTCritSectEnter returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return rc;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantCleanUpSessionsLocked(pThis);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Gets the state name.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns The state name string (read only).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param enmState The state.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic const char *supSvcGrantStateName(SUPSVCGRANTSTATE enmState)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (enmState)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Invalid: return "Invalid";
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Creating: return "Creating";
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Paused: return "Paused";
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Resuming: return "Resuming";
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Listen: return "Listen";
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Pausing: return "Pausing";
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Butchered: return "Butchered";
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Terminating: return "Terminating";
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Destroyed: return "Destroyed";
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default: return "?Unknown?";
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Attempts to flip into the butchered state.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns rc.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pThis The instance data.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param fOwnCritSect Whether we own the crit sect already.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pszFailed What failed.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param rc What to return (lazy bird).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcGrantThreadButchered(PSUPSVCGRANT pThis, bool fOwnCritSect, const char *pszFailed, int rc)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc2 = VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (!fOwnCritSect)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc2 = RTCritSectEnter(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc2))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantThread(%s): Butchered; %Rrc: %s",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantStateName(pThis->enmState), rc, pszFailed);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->enmState = kSupSvcGrantState_Butchered;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return rc;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Creates a new session.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns VINF_SUCCESS on success, VBox error code on internal error.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pThis Pointer to the grant service instance data.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param hSession The client session handle.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcGrantThreadCreateSession(PSUPSVCGRANT pThis, RTLOCALIPCSESSION hSession)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Allocate and initialize a new session instance before entering the critsect.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PSUPSVCGRANTSESSION pSession = (PSUPSVCGRANTSESSION)RTMemAlloc(sizeof(*pSession));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (!pSession)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantThreadListen: failed to allocate session");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VINF_SUCCESS; /* not fatal? */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pSession->pPrev = NULL;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pSession->pNext = NULL;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pSession->pParent = pThis;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pSession->hSession = hSession;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pSession->fTerminate = false;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pSession->hThread = NIL_RTTHREAD;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Enter the critsect, check the state, link it and fire off the session thread.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = RTCritSectEnter(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* check the state */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SUPSVCGRANTSTATE enmState = pThis->enmState;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (enmState == kSupSvcGrantState_Listen)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* link it */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pSession->pNext = pThis->pSessionHead;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (pThis->pSessionHead)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->pSessionHead->pPrev = pSession;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->pSessionHead = pSession;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* fire up the thread */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("supSvcGrantThreadListen: starting session %p\n", pSession));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTThreadCreate(&pSession->hThread, supSvcGrantSessionThread, pSession, 0,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "SESSION");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcGrantThreadButchered(pThis, false /* fOwnCritSect */, "RTCritSectLeave", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Successfully handled the client.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* bail out */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantThreadListen: RTThreadCreate returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("supSvcGrantThreadListen: dropping connection, state %s\n", supSvcGrantStateName(enmState)));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantThreadButchered(pThis, false /* fOwnCritSect */, "RTCritSectEnter", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLocalIpcSessionClose(hSession);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTMemFree(pSession);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return rc;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Listen for a client session and kicks off the service thread for it.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns VINF_SUCCESS on normal state change, failure if something gets screwed up.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pThis Pointer to the grant service instance data.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcGrantThreadListen(PSUPSVCGRANT pThis)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Wait for a client to connect and create a new session.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLOCALIPCSESSION hClientSession = NIL_RTLOCALIPCSESSION;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = RTLocalIpcServerListen(pThis->hServer, &hClientSession);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (rc == VERR_CANCELLED)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlow(("supSvcGrantThreadListen: cancelled\n"));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (rc == VERR_TRY_AGAIN)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* for testing */;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcGrantThreadButchered(pThis, false /* fOwnCritSect */, "RTLocalIpcServerListen", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcGrantThreadCreateSession(pThis, hClientSession);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Grant service thread.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * This thread is the one listening for clients and kicks off
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * the session threads and stuff.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns VINF_SUCCESS on normal exit, VBox error status on failure.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param hThread The thread handle.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvThis Pointer to the grant service instance data.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic DECLCALLBACK(int) supSvcGrantThread(RTTHREAD hThread, void *pvThis)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PSUPSVCGRANT pThis = (PSUPSVCGRANT)pvThis;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * The state loop.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync for (;;)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Switch on the current state (requires critsect).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = RTCritSectEnter(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantThread - RTCritSectEnter returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return rc;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SUPSVCGRANTSTATE enmState = pThis->enmState;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlow(("supSvcGrantThread: switching %s\n", supSvcGrantStateName(enmState)));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (enmState)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Creating:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Pausing:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->enmState = kSupSvcGrantState_Paused;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTSemEventSignal(pThis->hResponseEvent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcGrantThreadButchered(pThis, true /* fOwnCritSect*/, "RTSemEventSignal", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* fall thru */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Paused:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTThreadUserWait(hThread, 60*1000); /* wake up once in a while (paranoia) */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc) && rc != VERR_TIMEOUT)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcGrantThreadButchered(pThis, false /* fOwnCritSect*/, "RTThreadUserWait", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Resuming:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->enmState = kSupSvcGrantState_Listen;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTSemEventSignal(pThis->hResponseEvent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcGrantThreadButchered(pThis, true /* fOwnCritSect*/, "RTSemEventSignal", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* fall thru */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Listen:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = supSvcGrantThreadListen(pThis);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("supSvcGrantThread: supSvcGrantDoListening returns %Rrc, exiting\n", rc));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return rc;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Terminating:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("supSvcGrantThread: Done\n"));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcGrantState_Butchered:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcGrantThreadButchered(pThis, true /* fOwnCritSect*/, "Bad state", VERR_INTERNAL_ERROR);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Massage the session list between clients and states.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = supSvcGrantCleanUpSessions(pThis, false /* fOwnCritSect */);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcGrantThreadButchered(pThis, false /* fOwnCritSect */, "supSvcGrantCleanUpSessions", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Waits for the service thread to respond to a state change.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns VINF_SUCCESS on success, VERR_TIMEOUT if it doesn't respond in time, other error code on internal error.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pThis Pointer to the grant service instance data.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param enmCurState The current state.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param enmNewState The new state we're waiting for it to enter.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcGrantWait(PSUPSVCGRANT pThis, SUPSVCGRANTSTATE enmCurState, SUPSVCGRANTSTATE enmNewState)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlow(("supSvcGrantWait(,%s,%s): enter\n",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantStateName(enmCurState), supSvcGrantStateName(enmNewState)));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Wait a short while for the response event to be set.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTSemEventWait(pThis->hResponseEvent, 1000);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = RTCritSectEnter(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (pThis->enmState == enmNewState)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (pThis->enmState == enmCurState)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Wait good while longer.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTSemEventWait(pThis->hResponseEvent, 59*1000); /* 59 sec */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc) || rc == VERR_TIMEOUT)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTCritSectEnter(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Check the state whether we've succeeded.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SUPSVCGRANTSTATE enmState = pThis->enmState;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (enmState == enmNewState)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (enmState == enmCurState)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantWait(,%s,%s) - the thread doesn't respond in a timely manner, failing.",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantStateName(enmCurState), supSvcGrantStateName(enmNewState));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = VERR_TIMEOUT;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantWait(,%s,%s) - wrong state %s!", supSvcGrantStateName(enmCurState),
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantStateName(enmNewState), supSvcGrantStateName(enmState));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync AssertMsgFailed(("%s\n", supSvcGrantStateName(enmState)));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = VERR_INTERNAL_ERROR;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantWait(,%s,%s) - RTCritSectEnter returns %Rrc",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantStateName(enmCurState), supSvcGrantStateName(enmNewState));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantWait(,%s,%s) - RTSemEventWait returns %Rrc",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantStateName(enmCurState), supSvcGrantStateName(enmNewState));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantWait(,%s,%s) - wrong state %s!", supSvcGrantStateName(enmCurState),
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantStateName(enmNewState), supSvcGrantStateName(pThis->enmState));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync AssertMsgFailed(("%s\n", supSvcGrantStateName(pThis->enmState)));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = VERR_INTERNAL_ERROR;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantWait(,%s,%s) - RTCritSectEnter returns %Rrc",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantStateName(enmCurState), supSvcGrantStateName(enmNewState));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("supSvcGrantWait(,%s,%s): returns %Rrc\n",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantStateName(enmCurState), supSvcGrantStateName(enmNewState), rc));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return rc;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** @copydoc SUPSVCSERVICE::pfnCreate */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLCALLBACK(int) supSvcGrantCreate(void **ppvInstance)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlowFuncEnter();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Allocate and initialize the session data.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PSUPSVCGRANT pThis = (PSUPSVCGRANT)RTMemAlloc(sizeof(*pThis));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (!pThis)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantCreate - no memory");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VERR_NO_MEMORY;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync bool fFreeIt = true;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->pSessionHead = NULL;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->enmState = kSupSvcGrantState_Creating;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = RTCritSectInit(&pThis->VerifyCritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTCritSectInit(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTSemEventCreate(&pThis->hResponseEvent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTSemEventCreate(&pThis->hSessionEvent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Create the local IPC instance and then finally fire up the thread.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTLocalIpcServerCreate(&pThis->hServer, SUPSVC_GRANT_SERVICE_NAME, RTLOCALIPC_FLAGS_MULTI_SESSION);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTThreadCreate(&pThis->hThread, supSvcGrantThread, pThis, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "GRANT");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = supSvcGrantWait(pThis, kSupSvcGrantState_Creating, kSupSvcGrantState_Paused);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Successfully created the grant service!
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("supSvcGrantCreate: returns VINF_SUCCESS (pThis=%p)\n", pThis));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *ppvInstance = pThis;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * The thread FAILED to start in a timely manner!
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectEnter(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->enmState = kSupSvcGrantState_Terminating;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTThreadUserSignal(pThis->hThread);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int cTries = 10;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc2 = RTThreadWait(pThis->hThread, 20000, NULL);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc2))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* poke it a few more times before giving up. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync while (--cTries > 0)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTThreadUserSignal(pThis->hThread);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLocalIpcServerCancel(pThis->hServer);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RTThreadWait(pThis->hThread, 1000, NULL) != VERR_TIMEOUT)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync fFreeIt = cTries <= 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantCreate - RTThreadCreate returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLocalIpcServerDestroy(pThis->hServer);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->hServer = NIL_RTLOCALIPCSERVER;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantCreate - RTLocalIpcServiceCreate returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTSemEventDestroy(pThis->hSessionEvent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->hSessionEvent = NIL_RTSEMEVENT;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantCreate - RTSemEventCreate returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTSemEventDestroy(pThis->hResponseEvent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->hResponseEvent = NIL_RTSEMEVENT;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantCreate - RTSemEventCreate returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectDelete(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantCreate - RTCritSectInit returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectDelete(&pThis->VerifyCritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantCreate - RTCritSectInit returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (fFreeIt)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTMemFree(pThis);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("supSvcGrantCreate: returns %Rrc\n", rc));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return rc;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** @copydoc SUPSVCSERVICE::pfnStart */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLCALLBACK(void) supSvcGrantStart(void *pvInstance)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PSUPSVCGRANT pThis = (PSUPSVCGRANT)pvInstance;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Change the state and signal the thread.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = RTCritSectEnter(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync bool fInCritSect = true;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SUPSVCGRANTSTATE enmState = pThis->enmState;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (enmState == kSupSvcGrantState_Paused)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->enmState = kSupSvcGrantState_Resuming;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTThreadUserSignal(pThis->hThread);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Wait for the bugger to respond (no need to bitch here).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantWait(pThis, kSupSvcGrantState_Resuming, kSupSvcGrantState_Listen);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync fInCritSect = false;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantStart - Incorrect state %s!", supSvcGrantStateName(enmState));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (fInCritSect)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantStart - RTCritSectEnter returns %Rrc!", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync AssertRCReturnVoid(rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** @copydoc SUPSVCSERVICE::pfnTryStop */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLCALLBACK(int) supSvcGrantTryStop(void *pvInstance)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PSUPSVCGRANT pThis = (PSUPSVCGRANT)pvInstance;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Don't give up immediately.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync uint64_t u64StartTS = RTTimeMilliTS();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync for (;;)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * First check the state to make sure the thing is actually running.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * If the critsect is butchered, just pretend success.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTCritSectEnter(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantTryStop - RTCritSectEnter returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync AssertRC(rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SUPSVCGRANTSTATE enmState = pThis->enmState;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (enmState != kSupSvcGrantState_Listen)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantTryStop - Not running, state: %s", supSvcGrantStateName(enmState));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * If there are no clients, usher the thread into the paused state.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantCleanUpSessionsLocked(pThis);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (!pThis->pSessionHead)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTThreadUserReset(pThis->hThread);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->enmState = kSupSvcGrantState_Pausing;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc2 = RTLocalIpcServerCancel(pThis->hServer);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc3 = RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc) && RT_SUCCESS(rc2) && RT_SUCCESS(rc3))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantWait(pThis, kSupSvcGrantState_Pausing, kSupSvcGrantState_Paused);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantTryStop - RTThreadUserReset returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc2))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantTryStop - RTLocalIpcServerCancel returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc3))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantTryStop - RTCritSectLeave returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Check the time limit, otherwise wait for a client event.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync uint64_t u64Elapsed = RTTimeMilliTS() - u64StartTS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (u64Elapsed >= 60*1000) /* 1 min */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync unsigned cSessions = 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync for (PSUPSVCGRANTSESSION pCur = pThis->pSessionHead; pCur; pCur = pCur->pNext)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync cSessions++;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantTryStop - %u active sessions after waiting %u ms", cSessions, (unsigned)u64Elapsed);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VERR_TRY_AGAIN;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantTryStop - RTCritSectLeave returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTSemEventWait(pThis->hSessionEvent, 60*1000 - u64Elapsed);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc) && rc != VERR_TIMEOUT)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantTryStop - RTSemEventWait returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return VINF_SUCCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** @copydoc SUPSVCSERVICE::pfnStopAndDestroy */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLCALLBACK(void) supSvcGrantStopAndDestroy(void *pvInstance, bool fRunning)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync PSUPSVCGRANT pThis = (PSUPSVCGRANT)pvInstance;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Attempt to stop the service, cancelling blocked server and client calls.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectEnter(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SUPSVCGRANTSTATE enmState = pThis->enmState;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync AssertMsg(fRunning == (pThis->enmState == kSupSvcGrantState_Listen),
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync ("%RTbool %s\n", fRunning, supSvcGrantStateName(enmState)));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (enmState == kSupSvcGrantState_Listen)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTThreadUserReset(pThis->hThread);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->enmState = kSupSvcGrantState_Paused;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync for (PSUPSVCGRANTSESSION pCur = pThis->pSessionHead; pCur; pCur = pCur->pNext)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync ASMAtomicWriteBool(&pCur->fTerminate, true);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* try cancel local ipc operations that might be pending */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLocalIpcServerCancel(pThis->hServer);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync for (PSUPSVCGRANTSESSION pCur = pThis->pSessionHead; pCur; pCur = pCur->pNext)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLOCALIPCSESSION hSession;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync ASMAtomicReadHandle(&pCur->hSession, &hSession);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (hSession != NIL_RTLOCALIPCSESSION)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLocalIpcSessionCancel(hSession);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Wait for the thread to respond (outside the crit sect).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantWait(pThis, kSupSvcGrantState_Pausing, kSupSvcGrantState_Paused);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectEnter(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Wait for any lingering sessions to exit.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantCleanUpSessionsLocked(pThis);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (pThis->pSessionHead)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync uint64_t u64StartTS = RTTimeMilliTS();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync do
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* Destroy the sessions since cancelling didn't do the trick. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync for (PSUPSVCGRANTSESSION pCur = pThis->pSessionHead; pCur; pCur = pCur->pNext)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLOCALIPCSESSION hSession;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync ASMAtomicXchgHandle(&pCur->hSession, NIL_RTLOCALIPCSESSION, &hSession);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (hSession != NIL_RTLOCALIPCSESSION)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTLocalIpcSessionClose(hSession);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync AssertRC(rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantStopAndDestroy: RTLocalIpcSessionClose(%p) returns %Rrc",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync (uintptr_t)hSession, rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* Check the time. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync uint64_t u64Elapsed = RTTimeMilliTS() - u64StartTS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (u64Elapsed >= 60*1000) /* 1 min */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* wait */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTSemEventWait(pThis->hSessionEvent, 60*1000 - u64Elapsed);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectEnter(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc) && rc != VERR_TIMEOUT)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* cleanup and check again */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantCleanUpSessionsLocked(pThis);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync } while (pThis->pSessionHead);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Tell the service thread to terminate and wait for it to do so.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->enmState = kSupSvcGrantState_Terminating;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLOCALIPCSERVER hServer;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync ASMAtomicXchgHandle(&pThis->hServer, NIL_RTLOCALIPCSERVER, &hServer);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTThreadUserSignal(pThis->hThread);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTThreadWait(pThis->hThread, 20*1000, NULL);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc) && rc == VERR_TIMEOUT)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTThreadUserSignal(pThis->hThread);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLocalIpcServerDestroy(hServer);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync hServer = NIL_RTLOCALIPCSERVER;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTThreadWait(pThis->hThread, 40*1000, NULL);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantStopAndDestroy - RTThreadWait(40 sec) returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantStopAndDestroy - RTThreadWait(20 sec) returns %Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->hThread = NIL_RTTHREAD;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Kill the parent pointers of any lingering sessions.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectEnter(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->enmState = kSupSvcGrantState_Destroyed;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcGrantCleanUpSessionsLocked(pThis);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync unsigned cSessions = 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync for (PSUPSVCGRANTSESSION pCur = pThis->pSessionHead; pCur; pCur = pCur->pNext)
060db742c6ecb43560beec8754fb5b9c13bd7856vboxsync ASMAtomicWriteNullPtr(&pCur->pParent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectLeave(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (cSessions)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("supSvcGrantStopAndDestroy: %d session failed to terminate!", cSessions);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Free the resource.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTLocalIpcServerDestroy(hServer);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTSemEventDestroy(pThis->hResponseEvent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->hResponseEvent = NIL_RTSEMEVENT;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTSemEventDestroy(pThis->hSessionEvent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync pThis->hSessionEvent = NIL_RTSEMEVENT;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectDelete(&pThis->VerifyCritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTCritSectDelete(&pThis->CritSect);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTMemFree(pThis);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Log(("supSvcGrantStopAndDestroy: done (rc=%Rrc)\n", rc));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync