VirtualBox

source: vbox/trunk/src/VBox/Main/VirtualBoxClientImpl.cpp@ 34575

Last change on this file since 34575 was 34424, checked in by vboxsync, 14 years ago

Main/VirtualBoxClient: don't provide empty ctor/dtors, on OSX this causes a build break, probably because the factory magic provides them already

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.4 KB
Line 
1/* $Id: VirtualBoxClientImpl.cpp 34424 2010-11-26 18:40:56Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "VirtualBoxClientImpl.h"
19
20#include "AutoCaller.h"
21#include "VBoxEvents.h"
22#include "Logging.h"
23
24#include <iprt/thread.h>
25#include <iprt/critsect.h>
26#include <iprt/semaphore.h>
27#include <iprt/cpp/utils.h>
28
29
30/** Waiting time between probing whether VBoxSVC is alive. */
31#define VBOXCLIENT_DEFAULT_INTERVAL 30000
32
33
34// constructor / destructor
35/////////////////////////////////////////////////////////////////////////////
36
37HRESULT VirtualBoxClient::FinalConstruct()
38{
39 return init();
40}
41
42void VirtualBoxClient::FinalRelease()
43{
44 uninit();
45}
46
47// public initializer/uninitializer for internal purposes only
48/////////////////////////////////////////////////////////////////////////////
49
50/**
51 * Initializes the VirtualBoxClient object.
52 *
53 * @returns COM result indicator
54 */
55HRESULT VirtualBoxClient::init()
56{
57 LogFlowThisFunc(("\n"));
58
59 HRESULT rc;
60 /* Enclose the state transition NotReady->InInit->Ready */
61 AutoInitSpan autoInitSpan(this);
62 AssertReturn(autoInitSpan.isOk(), E_FAIL);
63
64 rc = unconst(mData.m_pVirtualBox).createLocalObject(CLSID_VirtualBox);
65 AssertComRCReturnRC(rc);
66
67 rc = unconst(mData.m_pEventSource).createObject();
68 AssertComRCReturnRC(rc);
69 rc = mData.m_pEventSource->init(static_cast<IVirtualBoxClient *>(this));
70 AssertComRCReturnRC(rc);
71
72 /* Setting up the VBoxSVC watcher thread. If anything goes wrong here it
73 * is not considered important enough to cause any sort of visible
74 * failure. The monitoring will not be done, but that's all. */
75 mData.m_ThreadWatcher = NIL_RTTHREAD;
76 int vrc = RTSemEventCreate(&mData.m_SemEvWatcher);
77 AssertRC(vrc);
78 if (RT_SUCCESS(vrc))
79 {
80 vrc = RTThreadCreate(&mData.m_ThreadWatcher, SVCWatcherThread,
81 this, 0, RTTHREADTYPE_INFREQUENT_POLLER,
82 RTTHREADFLAGS_WAITABLE, "VBoxSVCWatcher");
83 AssertRC(vrc);
84 }
85 else
86 {
87 RTSemEventDestroy(mData.m_SemEvWatcher);
88 mData.m_SemEvWatcher = NIL_RTSEMEVENT;
89 }
90
91 /* Confirm a successful initialization */
92 autoInitSpan.setSucceeded();
93
94 return rc;
95}
96
97/**
98 * Uninitializes the instance and sets the ready flag to FALSE.
99 * Called either from FinalRelease() or by the parent when it gets destroyed.
100 */
101void VirtualBoxClient::uninit()
102{
103 LogFlowThisFunc(("\n"));
104
105 /* Enclose the state transition Ready->InUninit->NotReady */
106 AutoUninitSpan autoUninitSpan(this);
107 if (autoUninitSpan.uninitDone())
108 return;
109
110 unconst(mData.m_pVirtualBox).setNull();
111
112 if (mData.m_ThreadWatcher != NIL_RTTHREAD)
113 {
114 /* Signal the event semaphore and wait for the thread to terminate.
115 * if it hangs for some reason exit anyway, this can cause a crash
116 * though as the object will no longer be available. */
117 RTSemEventSignal(mData.m_SemEvWatcher);
118 RTThreadWait(mData.m_ThreadWatcher, 30000, NULL);
119 mData.m_ThreadWatcher = NIL_RTTHREAD;
120 RTSemEventDestroy(mData.m_SemEvWatcher);
121 mData.m_SemEvWatcher = NIL_RTSEMEVENT;
122 }
123}
124
125// IVirtualBoxClient properties
126/////////////////////////////////////////////////////////////////////////////
127
128/**
129 * Returns a reference to the VirtualBox object.
130 *
131 * @returns COM status code
132 * @param aVirtualBox Address of result variable.
133 */
134STDMETHODIMP VirtualBoxClient::COMGETTER(VirtualBox)(IVirtualBox **aVirtualBox)
135{
136 CheckComArgOutPointerValid(aVirtualBox);
137
138 AutoCaller autoCaller(this);
139 if (FAILED(autoCaller.rc())) return autoCaller.rc();
140
141 /* this is const, no need to lock */
142 mData.m_pVirtualBox.queryInterfaceTo(aVirtualBox);
143 return S_OK;
144}
145
146/**
147 * Create a new Session object and return a reference to it.
148 *
149 * @returns COM status code
150 * @param aSession Address of result variable.
151 */
152STDMETHODIMP VirtualBoxClient::COMGETTER(Session)(ISession **aSession)
153{
154 HRESULT rc;
155 CheckComArgOutPointerValid(aSession);
156
157 AutoCaller autoCaller(this);
158 if (FAILED(autoCaller.rc())) return autoCaller.rc();
159
160 /* this is not stored in this object, no need to lock */
161 ComPtr<ISession> pSession;
162 rc = pSession.createInprocObject(CLSID_Session);
163 if (SUCCEEDED(rc))
164 pSession.queryInterfaceTo(aSession);
165
166 return rc;
167}
168
169/**
170 * Return reference to the EventSource associated with this object.
171 *
172 * @returns COM status code
173 * @param aEventSource Address of result variable.
174 */
175STDMETHODIMP VirtualBoxClient::COMGETTER(EventSource)(IEventSource **aEventSource)
176{
177 CheckComArgOutPointerValid(aEventSource);
178
179 AutoCaller autoCaller(this);
180 if (FAILED(autoCaller.rc())) return autoCaller.rc();
181
182 /* this is const, no need to lock */
183 mData.m_pEventSource.queryInterfaceTo(aEventSource);
184
185 return mData.m_pEventSource.isNull() ? E_FAIL : S_OK;
186}
187
188// private methods
189/////////////////////////////////////////////////////////////////////////////
190
191/*static*/
192DECLCALLBACK(int) VirtualBoxClient::SVCWatcherThread(RTTHREAD ThreadSelf,
193 void *pvUser)
194{
195 NOREF(ThreadSelf);
196 Assert(pvUser);
197 VirtualBoxClient *pThis = (VirtualBoxClient *)pvUser;
198 RTSEMEVENT sem = pThis->mData.m_SemEvWatcher;
199 RTMSINTERVAL cMillies = VBOXCLIENT_DEFAULT_INTERVAL;
200 int vrc;
201
202 /* The likelihood of early crashes are high, so start with a short wait. */
203 vrc = RTSemEventWait(sem, cMillies / 2);
204
205 /* As long as the waiting times out keep retrying the wait. */
206 while (RT_FAILURE(vrc))
207 {
208 {
209 HRESULT rc = S_OK;
210 ComPtr<IVirtualBox> pV = pThis->mData.m_pVirtualBox;
211 if (!pV.isNull())
212 {
213 ULONG rev;
214 rc = pV->COMGETTER(Revision)(&rev);
215 if (FAILED_DEAD_INTERFACE(rc))
216 {
217 LogRel(("VirtualBoxClient: detected unresponsive VBoxSVC (rc=%Rhrc)\n", rc));
218 fireVBoxSVCUnavailableEvent(pThis->mData.m_pEventSource);
219
220 /* Throw away the VirtualBox reference, it's no longer
221 * usable as VBoxSVC terminated in the mean time. */
222 unconst(pThis->mData.m_pVirtualBox).setNull();
223 }
224 }
225 else
226 {
227 /* Try to get a new VirtualBox reference straight away, and if
228 * this fails use an increased waiting time as very frequent
229 * restart attempts in some wedged config can cause high CPU
230 * and disk load. */
231 rc = unconst(pThis->mData.m_pVirtualBox).createLocalObject(CLSID_VirtualBox);
232 if (FAILED(rc))
233 cMillies = 3 * VBOXCLIENT_DEFAULT_INTERVAL;
234 else
235 cMillies = VBOXCLIENT_DEFAULT_INTERVAL;
236 }
237 }
238 vrc = RTSemEventWait(sem, cMillies);
239 }
240 return 0;
241}
242
243/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette