VirtualBox

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

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

Main/VirtualBoxClient: fix release log message

  • 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 34423 2010-11-26 18:02:26Z 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
37DEFINE_EMPTY_CTOR_DTOR(VirtualBoxClient)
38
39HRESULT VirtualBoxClient::FinalConstruct()
40{
41 return init();
42}
43
44void VirtualBoxClient::FinalRelease()
45{
46 uninit();
47}
48
49// public initializer/uninitializer for internal purposes only
50/////////////////////////////////////////////////////////////////////////////
51
52/**
53 * Initializes the VirtualBoxClient object.
54 *
55 * @returns COM result indicator
56 */
57HRESULT VirtualBoxClient::init()
58{
59 LogFlowThisFunc(("\n"));
60
61 HRESULT rc;
62 /* Enclose the state transition NotReady->InInit->Ready */
63 AutoInitSpan autoInitSpan(this);
64 AssertReturn(autoInitSpan.isOk(), E_FAIL);
65
66 rc = unconst(mData.m_pVirtualBox).createLocalObject(CLSID_VirtualBox);
67 AssertComRCReturnRC(rc);
68
69 rc = unconst(mData.m_pEventSource).createObject();
70 AssertComRCReturnRC(rc);
71 rc = mData.m_pEventSource->init(static_cast<IVirtualBoxClient *>(this));
72 AssertComRCReturnRC(rc);
73
74 /* Setting up the VBoxSVC watcher thread. If anything goes wrong here it
75 * is not considered important enough to cause any sort of visible
76 * failure. The monitoring will not be done, but that's all. */
77 mData.m_ThreadWatcher = NIL_RTTHREAD;
78 int vrc = RTSemEventCreate(&mData.m_SemEvWatcher);
79 AssertRC(vrc);
80 if (RT_SUCCESS(vrc))
81 {
82 vrc = RTThreadCreate(&mData.m_ThreadWatcher, SVCWatcherThread,
83 this, 0, RTTHREADTYPE_INFREQUENT_POLLER,
84 RTTHREADFLAGS_WAITABLE, "VBoxSVCWatcher");
85 AssertRC(vrc);
86 }
87 else
88 {
89 RTSemEventDestroy(mData.m_SemEvWatcher);
90 mData.m_SemEvWatcher = NIL_RTSEMEVENT;
91 }
92
93 /* Confirm a successful initialization */
94 autoInitSpan.setSucceeded();
95
96 return rc;
97}
98
99/**
100 * Uninitializes the instance and sets the ready flag to FALSE.
101 * Called either from FinalRelease() or by the parent when it gets destroyed.
102 */
103void VirtualBoxClient::uninit()
104{
105 LogFlowThisFunc(("\n"));
106
107 /* Enclose the state transition Ready->InUninit->NotReady */
108 AutoUninitSpan autoUninitSpan(this);
109 if (autoUninitSpan.uninitDone())
110 return;
111
112 unconst(mData.m_pVirtualBox).setNull();
113
114 if (mData.m_ThreadWatcher != NIL_RTTHREAD)
115 {
116 /* Signal the event semaphore and wait for the thread to terminate.
117 * if it hangs for some reason exit anyway, this can cause a crash
118 * though as the object will no longer be available. */
119 RTSemEventSignal(mData.m_SemEvWatcher);
120 RTThreadWait(mData.m_ThreadWatcher, 30000, NULL);
121 mData.m_ThreadWatcher = NIL_RTTHREAD;
122 RTSemEventDestroy(mData.m_SemEvWatcher);
123 mData.m_SemEvWatcher = NIL_RTSEMEVENT;
124 }
125}
126
127// IVirtualBoxClient properties
128/////////////////////////////////////////////////////////////////////////////
129
130/**
131 * Returns a reference to the VirtualBox object.
132 *
133 * @returns COM status code
134 * @param aVirtualBox Address of result variable.
135 */
136STDMETHODIMP VirtualBoxClient::COMGETTER(VirtualBox)(IVirtualBox **aVirtualBox)
137{
138 CheckComArgOutPointerValid(aVirtualBox);
139
140 AutoCaller autoCaller(this);
141 if (FAILED(autoCaller.rc())) return autoCaller.rc();
142
143 /* this is const, no need to lock */
144 mData.m_pVirtualBox.queryInterfaceTo(aVirtualBox);
145 return S_OK;
146}
147
148/**
149 * Create a new Session object and return a reference to it.
150 *
151 * @returns COM status code
152 * @param aSession Address of result variable.
153 */
154STDMETHODIMP VirtualBoxClient::COMGETTER(Session)(ISession **aSession)
155{
156 HRESULT rc;
157 CheckComArgOutPointerValid(aSession);
158
159 AutoCaller autoCaller(this);
160 if (FAILED(autoCaller.rc())) return autoCaller.rc();
161
162 /* this is not stored in this object, no need to lock */
163 ComPtr<ISession> pSession;
164 rc = pSession.createInprocObject(CLSID_Session);
165 if (SUCCEEDED(rc))
166 pSession.queryInterfaceTo(aSession);
167
168 return rc;
169}
170
171/**
172 * Return reference to the EventSource associated with this object.
173 *
174 * @returns COM status code
175 * @param aEventSource Address of result variable.
176 */
177STDMETHODIMP VirtualBoxClient::COMGETTER(EventSource)(IEventSource **aEventSource)
178{
179 CheckComArgOutPointerValid(aEventSource);
180
181 AutoCaller autoCaller(this);
182 if (FAILED(autoCaller.rc())) return autoCaller.rc();
183
184 /* this is const, no need to lock */
185 mData.m_pEventSource.queryInterfaceTo(aEventSource);
186
187 return mData.m_pEventSource.isNull() ? E_FAIL : S_OK;
188}
189
190// private methods
191/////////////////////////////////////////////////////////////////////////////
192
193/*static*/
194DECLCALLBACK(int) VirtualBoxClient::SVCWatcherThread(RTTHREAD ThreadSelf,
195 void *pvUser)
196{
197 NOREF(ThreadSelf);
198 Assert(pvUser);
199 VirtualBoxClient *pThis = (VirtualBoxClient *)pvUser;
200 RTSEMEVENT sem = pThis->mData.m_SemEvWatcher;
201 RTMSINTERVAL cMillies = VBOXCLIENT_DEFAULT_INTERVAL;
202 int vrc;
203
204 /* The likelihood of early crashes are high, so start with a short wait. */
205 vrc = RTSemEventWait(sem, cMillies / 2);
206
207 /* As long as the waiting times out keep retrying the wait. */
208 while (RT_FAILURE(vrc))
209 {
210 {
211 HRESULT rc = S_OK;
212 ComPtr<IVirtualBox> pV = pThis->mData.m_pVirtualBox;
213 if (!pV.isNull())
214 {
215 ULONG rev;
216 rc = pV->COMGETTER(Revision)(&rev);
217 if (FAILED_DEAD_INTERFACE(rc))
218 {
219 LogRel(("VirtualBoxClient: detected unresponsive VBoxSVC (rc=%Rhrc)\n", rc));
220 fireVBoxSVCUnavailableEvent(pThis->mData.m_pEventSource);
221
222 /* Throw away the VirtualBox reference, it's no longer
223 * usable as VBoxSVC terminated in the mean time. */
224 unconst(pThis->mData.m_pVirtualBox).setNull();
225 }
226 }
227 else
228 {
229 /* Try to get a new VirtualBox reference straight away, and if
230 * this fails use an increased waiting time as very frequent
231 * restart attempts in some wedged config can cause high CPU
232 * and disk load. */
233 rc = unconst(pThis->mData.m_pVirtualBox).createLocalObject(CLSID_VirtualBox);
234 if (FAILED(rc))
235 cMillies = 3 * VBOXCLIENT_DEFAULT_INTERVAL;
236 else
237 cMillies = VBOXCLIENT_DEFAULT_INTERVAL;
238 }
239 }
240 vrc = RTSemEventWait(sem, cMillies);
241 }
242 return 0;
243}
244
245/* 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