VirtualBoxImpl.cpp revision 3918ed075bc7939d7397b643c46b460a4f3b67fc
/* check hard disk consistency */ /// @todo (r=dmik) add IVirtualBox::cleanupHardDisks() instead or similar // for (HardDiskList::const_iterator it = mData.mHardDisks.begin(); // it != mData.mHardDisks.end() && SUCCEEDED (rc); // rc = (*it)->checkConsistency(); // CheckComRCBreakRC ((rc)); /// @todo (dmik) if successful, check for orphan (unused) diffs // that might be left because of the server crash, and remove // Hmm, is it the same remark as above?.. /* we assume that error info is set by the thrower */ /* start the client watcher thread */ /* start the async event handler thread */ /* wait until the thread sets mAsyncEventQ */ /* Confirm a successful initialization when it's the case */ LogFlow ((
"===========================================================\n"));
/* Enclose the state transition Ready->InUninit->NotReady */ LogFlow ((
"===========================================================\n"));
/* tell all our child objects we've been uninitialized */ #
endif /* VBOX_WITH_RESOURCE_USAGE_API */ /* Uninit all other children still referenced by clients (unregistered * machines, hard disks, DVD/floppy images, server-side progress /* unlock the config file */ /* release all callbacks */ /* signal to exit the event loop */ * Wait for thread termination (only if we've successfully posted /* signal the client watcher thread */ /* wait for the termination */ LogFlow ((
"===========================================================\n"));
// IVirtualBox properties ///////////////////////////////////////////////////////////////////////////// /* mHomeDir is const and doesn't need a lock */ /* mCfgFile.mName is const and doesn't need a lock */ /* mHost is const, no need to lock */ /* mSystemProperties is const, no need to lock */ /* protect mProgressOperations */ /* mPerformanceCollector is const, no need to lock */ #
else /* !VBOX_WITH_RESOURCE_USAGE_API */#
endif /* !VBOX_WITH_RESOURCE_USAGE_API *////////////////////////////////////////////////////////////////////////////// /** @note Locks mSystemProperties object for reading. */ tr (
"Machine name cannot be empty"));
/* Compose the settings file name using the following scheme: * <base_folder>/<machine_name>/<machine_name>.xml * If a non-null and non-empty base folder is specified, the default * machine folder will be used as a base folder. /* we use the non-full folder value below to keep the path relative */ /* create a new object */ /* Create UUID if an empty one was specified. */ /* initialize the machine object */ /* set the return value */ /* null and empty strings are not allowed as path names */ tr (
"Machine name cannot be empty"));
/* append the default extension if none */ /* create a new object */ /* Create UUID if an empty one was specified. */ /* initialize the machine object */ /* set the return value */ /* null and empty strings are not allowed as path names */ /* create a new object */ /* initialize the machine object */ /* set the return value */ /** @note Locks objects! */ * we can safely cast child to Machine * here because only Machine * implementations of IMachine can be among our children * this machine was not created by CreateMachine() * or opened by OpenMachine() or loaded during startup tr (
"The machine named '%ls' is not created within this " "VirtualBox instance"),
name.
raw());
/** @note Locks objects! */ /* the below will set *aMachine to NULL if machine is null */ /** @note Locks this object for reading, then some machine objects for reading. */ /* start with not found */ /* take a copy for safe iteration outside the lock */ /* skip inaccessible machines */ /* this will set (*machine) to NULL if machineObj is null */ tr (
"Could not find a registered machine named '%ls'"),
aName);
/** @note Locks objects! */ /* remove from the collection of registered machines */ /* save the global registry */ /* return the unregistered machine to the caller */ /* we don't access non-const data members so no need to lock */ /* we don't access non-const data members so no need to lock */ /* Note that it's important to call uninit() on failure to register * because the differencing hard disk would have been already associated * with the parent and this association needs to be broken. */ /* the below will set *aHardDisk to NULL if hardDisk is null */ /* the below will set *aHardDisk to NULL if hardDisk is null */ /** @note Doesn't lock anything. */ /* null and empty strings are not allowed as path names */ /* generate an UUID if not specified */ /** @note Locks objects! */ /* the below will set *aDVDImage to NULL if image is null */ /** @note Locks objects! */ /* the below will set *aDVDImage to NULL if dvd is null */ /** @note Doesn't lock anything. */ /* null and empty strings are not allowed as path names */ /* generate an UUID if not specified */ /** @note Locks objects! */ /* the below will set *aFloppyImage to NULL if image is null */ /** @note Locks objects! */ /* the below will set *aFloppyImage to NULL if img is null */ /** @note Locks this object for reading. */ tr (
"'%ls' is not a valid Guest OS type"),
* @note Locks this object for reading. /* start with nothing found */ /* serialize file access (prevent writes) */ /* load the settings file (we don't reuse the existing handle but * request a new one to allow for concurrent multithreaded reads) */ /* if we're supposed to return the first one */ /* did we find the key we're looking for? */ /* is there another item? */ /* else it's the last one, arguments are already NULL */ /* Here we are when a) there are no items at all or b) there are items * but none of them equals to the requested non-NULL key. b) is an * error as well as a) if the key is non-NULL. When the key is NULL * (which is the case only when there are no items), we just fall * through to return NULLs and S_OK. */ tr (
"Could not find the extra data key '%ls'"),
aKey);
* @note Locks this object for reading. /* start with nothing found */ /* serialize file access (prevent writes) */ /* load the settings file (we don't reuse the existing handle but * request a new one to allow for concurrent multithreaded reads) */ /* check if the key exists */ * @note Locks this object for writing. /* serialize file access (prevent concurrent reads and writes) */ /* load the settings file */ /* When no key is found, oldVal is null */ /* ask for permission from all listeners */ tr (
"Could not set extra data because someone refused " "the requested change of '%ls' to '%ls'%s%ls"),
/* an old value does for sure exist here (XML schema * guarantees that "value" may not absent in the * <ExtraDataItem> element) */ /* save settings on success */ /* fire a notification */ /* check the session state */ tr (
"The given session is already open or being opened"));
/* get the IInternalSessionControl interface */ * tell the client watcher thread to update the set of * machines that have open sessions /* check the session state */ tr (
"The given session is already open or being opened"));
/* get the IInternalSessionControl interface */ /* create a progress object */ Bstr (
tr (
"Spawning session")),
FALSE /* aCancelable */);
/* signal the client watcher thread */ /* check the session state */ tr (
"The given session is already open or being opened"));
/* get the IInternalSessionControl interface */ * @note Locks this object for writing. * @note Locks this object for writing. /* saveSettings() needs write lock */ /* perform backup only when there was auto-conversion */ // public methods only for internal purposes ///////////////////////////////////////////////////////////////////////////// * Posts an event to the event queue that is processed asynchronously * Posting events to the dedicated event queue is useful to perform secondary * actions outside any object locks -- for example, to iterate over a list * of callbacks and inform them about some change caused by some object's * @param event event to post * (must be allocated using |new|, will be deleted automatically * by the event thread after processing) * @note Doesn't lock any object. "the event is discarded!\n",
* Adds a progress to the global collection of pending operations. * Usually gets called upon progress object initialization. * @param aProgress Peration to add to the collection. * @note Doesn't lock objects. /* protect mProgressOperations */ * Removes the progress from the global collection of pending operations. * Usualy gets called upon progress completion. * @param aId UUID of the progress operation to remove * @note Doesn't lock objects. /* protect mProgressOperations */ * Helper method to that starts a worker thread that: * - creates a pipe communication channel using SVCHlpClient; * - starts a SVC Helper process that will inherit this channel; * - executes the supplied function by passing it the created SVCHlpClient * and opened instance to communicate to the Helper process and the given * The user function is supposed to communicate to the helper process * using the \a aClient argument to do the requested job and optionally expose * the prgress through the \a aProgress object. The user function should never * call notifyComplete() on it: this will be done automatically using the * result code returned by the function. * Before the user function is stared, the communication channel passed to in * the \a aClient argument, is fully set up, the function should start using * it's write() and read() methods directly. * The \a aVrc parameter of the user function may be used to return an error * code if it is related to communication errors (for example, returned by * the SVCHlpClient members when they fail). In this case, the correct error * message using this value will be reported to the caller. Note that the * value of \a aVrc is inspected only if the user function itself returns * If a failure happens anywhere before the user function would be normally * called, it will be called anyway in special "cleanup only" mode indicated * by \a aClient, \a aProgress and \aVrc arguments set to NULL. In this mode, * all the function is supposed to do is to cleanup its aUser argument if * necessary (it's assumed that the ownership of this argument is passed to * the user function once #startSVCHelperClient() returns a success, thus * making it responsible for the cleanup). * After the user function returns, the thread will send the SVCHlpMsg::Null * message to indicate a process termination. * @param aPrivileged |true| to start the SVC Hepler process as a privlieged * user that can perform administrative tasks * @param aFunc user function to run * @param aUser argument to the user function * @param aProgress progress object that will track operation completion * @note aPrivileged is currently ignored (due to some unsolved problems in * Vista) and the process will be started as a normal (unprivileged) * @note Doesn't lock anything. /* create the SVCHelperClientThread() argument */ static_cast <
void *> (d.
get()),
/* d is now owned by SVCHelperClientThread(), so release it */ * Worker thread for startSVCHelperClient(). /* protect VirtualBox from uninitialization */ tr (
"Could not create the communication channel (%Rrc)"),
vrc);
/* get the path to the executable */ /* Attempt to start a privileged process using the Run As dialog */ /* hide excessive details in case of a frequent error * (pressing the Cancel button to close the Run As dialog) */ tr (
"Operatiion cancelled by the user"));
tr (
"Could not launch a privileged process '%s' (%Rrc)"),
tr (
"Could not launch a process '%s' (%Rrc)"),
exePath,
vrc);
/* wait for the client to connect */ /* start the user supplied function */ /* send the termination signal to the process anyway */ tr (
"Could not operate the communication channel (%Rrc)"),
vrc);
/* call the user function in the "cleanup only" mode * to let it free resources passed to in aUser */ #
endif /* RT_OS_WINDOWS */ * Sends a signal to the client watcher thread to rescan the set of machines * that have open sessions. * @note Doesn't lock anything. /* sent an update request */ * Adds the given child process ID to the list of processes to be reaped. * This call should be followed by #updateClientWatcher() to take the effect. /** Event for onMachineStateChange(), onMachineDataChange(), onMachineRegistered() */ LogFlow ((
"OnMachineStateChange: id={%Ruuid}, state=%d\n",
LogFlow ((
"OnMachineRegistered: id={%Ruuid}, registered=%d\n",
* @note Doesn't lock any object. * @note Doesn't lock any object. * @note Locks this object for reading. /* if a call to this method fails for some reason (for ex., because * the other side is dead), we ensure allowChange stays true * (MS COM RPC implementation seems to zero all output vars before * issuing an IPC call or after a failure, so it's essential /** Event for onExtraDataChange() */ LogFlow ((
"OnExtraDataChange: machineId={%Ruuid}, key='%ls', val='%ls'\n",
* @note Doesn't lock any object. * @note Doesn't lock any object. /** Event for onSessionStateChange() */ LogFlow ((
"OnSessionStateChange: machineId={%Ruuid}, sessionState=%d\n",
* @note Doesn't lock any object. /** Event for onSnapshotTaken(), onSnapshotRemoved() and onSnapshotChange() */ LogFlow ((
"OnSnapshotTaken: machineId={%Ruuid}, snapshotId={%Ruuid}\n",
LogFlow ((
"OnSnapshotDiscarded: machineId={%Ruuid}, snapshotId={%Ruuid}\n",
LogFlow ((
"OnSnapshotChange: machineId={%Ruuid}, snapshotId={%Ruuid}\n",
* @note Doesn't lock any object. * @note Doesn't lock any object. * @note Doesn't lock any object. /** Event for onGuestPropertyChange() */ LogFlow ((
"OnGuestPropertyChange: machineId={%Ruuid}, name='%ls', value='%ls', flags='%ls'\n",
* @note Doesn't lock any object. * @note Locks this object for reading. /* unknown type must always be the first */ * Returns the list of opened machines (machines having direct sessions opened * by client processes) and optionally the list of direct session controls. * @param aMachines Where to put opened machines (will be empty if none). * @param aControls Where to put direct session controls (optional). * @note The returned lists contain smart pointers. So, clear it as soon as * it becomes no more necessary to release instances. * @note It can be possible that a session machine from the list has been * whenaccessing unprotected data directly. * @note Locks objects for reading. * Searches for a Machine object with the given ID in the collection * of registered machines. * if TRUE, the appropriate error info is set in case when the machine * where to store the found machine object (can be NULL) * S_OK when found or E_INVALIDARG when not found * @note Locks this object for reading. tr (
"Could not find a registered machine with UUID {%Ruuid}"),
* Searches for a HardDisk object with the given ID or location in the list of * registered hard disks. If both ID and location are specified, the first * object that matches either of them (not necessarily both) is returned. * @param aId ID of the hard disk (unused when NULL). * @param aLocation Full location specification (unused NULL). * @param aSetError If @c true , the appropriate error info is set in case * when the hard disk is not found. * @param aHardDisk Where to store the found hard disk object (can be NULL). * @return S_OK when found or E_INVALIDARG when not found. * @note Locks this object and hard disk objects for reading. /* first, look up by UUID in the map if UUID is provided */ /* then iterate and search by location */ setError (
rc,
tr (
"Could not find a hard disk with UUID {%Ruuid} " "in the media registry ('%ls')"),
setError (
rc,
tr (
"Could not find a hard disk with location '%ls' " "in the media registry ('%ls')"),
* Searches for a DVDImage2 object with the given ID or location in the list of * registered DVD images. If both ID and file path are specified, the first * object that matches either of them (not necessarily both) is returned. * @param aId ID of the DVD image (unused when NULL). * @param aLocation Full path to the image file (unused when NULL). * @param aSetError If @c true, the appropriate error info is set in case when * the image is not found. * @param aImage Where to store the found image object (can be NULL). * @return S_OK when found or E_INVALIDARG when not found. * @note Locks this object and image objects for reading. tr (
"Invalid image file location '%ls' (%Rrc)"),
/* no AutoCaller, registered image life time is bound to this */ "in the media registry ('%ls')"),
"in the media registry ('%ls')"),
* Searches for a FloppyImage2 object with the given ID or location in the * collection of registered DVD images. If both ID and file path are specified, * the first object that matches either of them (not necessarily both) is * @param aId ID of the DVD image (unused when NULL). * @param aLocation Full path to the image file (unused when NULL). * @param aSetError If @c true, the appropriate error info is set in case when * the image is not found. * @param aImage Where to store the found image object (can be NULL). * @return S_OK when found or E_INVALIDARG when not found. * @note Locks this object and image objects for reading. tr (
"Invalid image file location '%ls' (%Rrc)"),
/* no AutoCaller, registered image life time is bound to this */ setError (
rc,
tr (
"Could not find a floppy image with UUID {%Ruuid} " "in the media registry ('%ls')"),
"in the media registry ('%ls')"),
* Calculates the absolute path of the given path taking the VirtualBox home * directory as the current directory. * @param aPath Path to calculate the absolute path for. * @param aResult Where to put the result (used only on success, can be the * same Utf8Str instance as passed in @a aPath). * @note Doesn't lock any object. /* no need to lock since mHomeDir is const */ * Tries to calculate the relative path of the given absolute path using the * directory of the VirtualBox settings file as the base directory. * @param aPath Absolute path to calculate the relative path for. * @param aResult Where to put the result (used only when it's possible to * make a relative path from the given absolute path; otherwise * @note Doesn't lock any object. /* no need to lock since mHomeDir is const */ /* when assigning, we create a separate Utf8Str instance because both * aPath and aResult can point to the same memory location when this * func is called (if we just do aResult = aPath, aResult will be freed * first, and since its the same as aPath, an attempt to copy garbage ///////////////////////////////////////////////////////////////////////////// * Checks if there is a hard disk, DVD or floppy image with the given ID or * location already registered. * On return, sets @aConflict to the string describing the conflicting medium, * or sets it to @c Null if no conflicting media is found. Returns S_OK in * either case. A failure is unexpected. * @param aId UUID to check. * @param aLocation Location to check. * @param aConflict Where to return parameters of the conflicting medium. * @note Locks this object and media objects for reading. /* Note: no AutoCaller since bound to this */ tr (
"hard disk '%ls' with UUID {%Ruuid}"),
/* Note: no AutoCaller since bound to this */ tr (
"CD/DVD image '%ls' with UUID {%Ruuid}"),
/* Note: no AutoCaller since bound to this */ tr (
"floppy image '%ls' with UUID {%Ruuid}"),
* Reads in the machine definitions from the configuration loader * and creates the relevant objects. * @param aGlobal <Global> node. * @note Can be called only from #init(). * @note Doesn't lock anything. /* create a new machine object */ /* initialize the machine object and register it */ * Reads in the media registration entries from the global settings file * and creates the relevant objects. * @param aGlobal <Global> node * @note Can be called only from #init(). * @note Doesn't lock anything. const char *
kMediaNodes[] = {
"HardDisks",
"DVDImages",
"FloppyImages" };
/* All three media nodes are optional */ case 2:
/* FloppyImages */ * Helper function to write out the configuration tree. * @note Locks this object for writing and child objects for reading/writing! /* serialize file access (prevent concurrent reads and writes) */ /* load the settings file */ /* first, delete the entire machine registry */ /* write out the machines */ /* first, delete the entire media registry */ /* host data (USB filters) */ /* save the settings on success */ /* we assume that error info is set by the thrower */ * Helper to register the machine. * When called during VirtualBox startup, adds the given machine to the * collection of registered machines. Otherwise tries to mark the machine * as registered, and, if succeeded, adds it to the collection and * @note The caller must have added itself as a caller of the @a aMachine * object if calls this method not on VirtualBox startup. * @param aMachine machine to register tr (
"Registered machine with UUID {%Ruuid} ('%ls') already exists"),
/* Machine::trySetRegistered() will commit and save machine settings */ /* add to the collection of registered machines */ * Remembers the given hard disk by storing it in the hard disk registry. * @param aHardDisk Hard disk object to remember. * @param aSaveRegistry @c true to save hard disk registry to disk (default). * When @a aSaveRegistry is @c true, this operation may fail because of the * failed #saveSettings() method it calls. In this case, the hard disk object * will not be remembered. It is therefore the responsibility of the caller to * call this method as the last step of some action that requires registration * in order to make sure that only fully functional hard disk objects get * @note Locks this object for writing and @a aHardDisk for reading. tr (
"Cannot register the hard disk '%ls' with UUID {%Ruuid} " "because a %s already exists in the media registry ('%ls')"),
/* base (root) hard disk */ * Removes the given hard disk from the hard disk registry. * @param aHardDisk Hard disk object to remove. * @param aSaveRegistry @c true to save hard disk registry to disk (default). * When @a aSaveRegistry is @c true, this operation may fail because of the * failed #saveSettings() method it calls. In this case, the hard disk object * will NOT be removed from the registry when this method returns. It is * therefore the responsibility of the caller to call this method as the first * step of some action that requires unregistration, before calling uninit() on * @note Locks this object for writing and @a aHardDisk for reading. /* base (root) hard disk */ * Remembers the given image by storing it in the CD/DVD image registry. * @param aImage Image object to remember. * @param aSaveRegistry @c true to save the image registry to disk (default). * When @a aSaveRegistry is @c true, this operation may fail because of the * failed #saveSettings() method it calls. In this case, the image object * will not be remembered. It is therefore the responsibility of the caller to * call this method as the last step of some action that requires registration * in order to make sure that only fully functional image objects get * @note Locks this object for writing and @a aImage for reading. tr (
"Cannot register the CD/DVD image '%ls' with UUID {%Ruuid} " "because a %s already exists in the media registry ('%ls')"),
/* add to the collection */ * Removes the given image from the CD/DVD image registry registry. * @param aImage Image object to remove. * @param aSaveRegistry @c true to save hard disk registry to disk (default). * When @a aSaveRegistry is @c true, this operation may fail because of the * failed #saveSettings() method it calls. In this case, the image object * will NOT be removed from the registry when this method returns. It is * therefore the responsibility of the caller to call this method as the first * step of some action that requires unregistration, before calling uninit() on * @note Locks this object for writing and @a aImage for reading. * Remembers the given image by storing it in the floppy image registry. * @param aImage Image object to remember. * @param aSaveRegistry @c true to save the image registry to disk (default). * When @a aSaveRegistry is @c true, this operation may fail because of the * failed #saveSettings() method it calls. In this case, the image object * will not be remembered. It is therefore the responsibility of the caller to * call this method as the last step of some action that requires registration * in order to make sure that only fully functional image objects get * @note Locks this object for writing and @a aImage for reading. tr (
"Cannot register the floppy image '%ls' with UUID {%Ruuid} " "because a %s already exists in the media registry ('%ls')"),
/* add to the collection */ * Removes the given image from the floppy image registry registry. * @param aImage Image object to remove. * @param aSaveRegistry @c true to save hard disk registry to disk (default). * When @a aSaveRegistry is @c true, this operation may fail because of the * failed #saveSettings() method it calls. In this case, the image object * will NOT be removed from the registry when this method returns. It is * therefore the responsibility of the caller to call this method as the first * step of some action that requires unregistration, before calling uninit() on * @note Locks this object for writing and @a aImage for reading. * Attempts to cast from a raw interface pointer to an underlying object. * On sucess, @a aTo will contain the object reference. On failure, @a aTo will * be set to @c null and an extended error info will be returned. * @param aFrom Interface pointer to cast from. * @param aTo Where to store a reference to the underlying object. * @note Locks this object for reading. "within this VirtualBox instance"));
/* we can safely cast child to HardDisk * here because only HardDisk * implementations of IHardDisk can be among our children */ * Helper to update the global settings file when the name of some machine * changes so that file and directory renaming occurs. This method ensures that * all affected paths in the disk registry are properly updated. * @param aOldPath Old path (full). * @param aNewPath New path (full). * @note Locks this object + DVD, Floppy and HardDisk children for writing. /* check HardDisk paths */ * Creates the path to the specified file accoring to the path information * present in the file name. * Note that the given file name must contain the full path otherwise the * extracted reliative path will be created based on the current working * directory which is normally unknown. * @param aFileName Full file name which path needs to be created. * @return Extended error information on failure to create the path. tr (
"Could not create the directory '%s' (%Rrc)"),
* Helper method to load the setting tree and turn expected exceptions into * COM errors, according to arguments. * Note that this method will not catch unexpected errors so it may still * @param aTree Tree to load into settings. * @param aFile File to load settings from. * @param aValidate @c @true to enable tree validation. * @param aCatchLoadErrors @c true to catch exceptions caused by file * access or validation errors. * @param aAddDefaults @c true to cause the substitution of default * values for for missing attributes that have * defaults in the XML schema. * @param aFormatVersion Where to store the current format version of the * loaded settings tree (optional, may be NULL). /* on success, memorize the current settings file version or set it to * the most recent version if no settings conversion took place. Note * that it's not necessary to do it every time we load the settings file * (i.e. only loadSettingsTree_FirstTime() passes a non-NULL * aFormatVersion value) because currently we keep the settings * files locked so that the only legal way to change the format version * while VirtualBox is running is saveSettingsTree(). */ tr (
"Could not load the settings file '%s' (%Rrc)"),
tr (
"Could not load the settings file '%s'.\n%s"),
* Helper method to save the settings tree and turn expected exceptions to COM * Note that this method will not catch unexpected errors so it may still * @param aTree Tree to save. * @param aFile File to save the tree to. * @param aFormatVersion Where to store the (recent) format version of the * saved settings tree on success. /* set the current settings file version to the most recent version on * success. See also VirtualBox::loadSettingsTree(). */ /* this is the only expected exception for now */ tr (
"Could not save the settings file '%s' (%Rrc)"),
* Creates a backup copy of the given settings file by suffixing it with the * supplied version format string and optionally with numbers from .0 to .9 * if the backup file already exists. * @param aFileName Orignal settings file name. * @param aOldFormat Version of the original format. * @param aBakFileName File name of the created backup copy (only on success). /* try progressive suffix from .0 to .9 on failure */ tr (
"Could not copy the settings file '%s' to '%s' (%Rrc)"),
* Handles unexpected exceptions by turning them into COM errors in release * builds or by hitting a breakpoint in the release builds. rc = VirtualBox::handleUnexpectedExceptions (RT_SRC_POS); * @param RT_SRC_POS_DECL "RT_SRC_POS" macro instantiation. /* rethrow the current exception */ /* should not get here */ * Helper to lock the VirtualBox configuration for write access. * @note This method is not thread safe (must be called only from #init() * @note If the configuration file is not found, the method returns * S_OK, but subsequent #isConfigLocked() will return FALSE. This is used * in some places to determine the (valid) situation when no config file * exists yet, and therefore a new one should be created from scatch. /* open the associated config file */ * It is ok if the file is not found, it will be created by * init(). Otherwise return an error. tr (
"Could not lock the settings file '%ls' (%Rrc)"),
* Helper to unlock the VirtualBox configuration from write access. * @note This method is not thread safe (must be called only from #init() /** @todo flush the directory too. */ * Thread function that watches the termination of all client processes * that have opened sessions using IVirtualBox::OpenSession() /// @todo (dmik) processes reaping! /* VirtualBox has been early uninitialized, terminate */ /* release the caller to let uninit() ever proceed */ /* Restore the caller before using VirtualBox. If it fails, this * means VirtualBox is being uninitialized and we must terminate. */ /* update event is signaled */ /* machine mutex is released */ /* machine mutex is abandoned due to client process termination */ /* spawned VM process has terminated (normally or abnormally) */ /* close old process handles */ /* obtain a new set of opened machines */ /// @todo handle situations with more than 64 objects (
"MAXIMUM_WAIT_OBJECTS reached"));
/* obtain a new set of spawned machines */ /// @todo handle situations with more than 64 objects (
"MAXIMUM_WAIT_OBJECTS reached"));
/* close old process handles */ /* release sets of machines if any */ /// @todo (dmik) processes reaping! /* according to PMREF, 64 is the maximum for the muxwait list */ /* VirtualBox has been early uninitialized, terminate */ /* release the caller to let uninit() ever proceed */ /* Restore the caller before using VirtualBox. If it fails, this * means VirtualBox is being uninitialized and we must terminate. */ /* update event is signaled */ (
"RTSemEventWait returned %Rrc\n",
vrc));
/* are there any mutexes? */ /* figure out what's going on with machines */ /* machine mutex is normally released */ /* machine mutex is abandoned due to client process * termination; find which mutex is in the Owner Died /* close the dead mutex as asked by PMREF */ (
"DosWaitMuxWaitSem returned %d\n",
arc));
/* are there any spawning sessions? */ /* close the old muxsem */ /* obtain a new set of opened machines */ /// @todo handle situations with more than 64 objects (
"maximum of 64 mutex semaphores reached (%d)",
/* create a new muxsem */ (
"DosCreateMuxWaitSem returned %d\n",
arc));
/* obtain a new set of spawned machines */ /* release sets of machines if any */ /* release the caller to let uninit() ever proceed */ * Restore the caller before using VirtualBox. If it fails, this * means VirtualBox is being uninitialized and we must terminate. /* RT_SUCCESS (rc) means an update event is signaled */ /* obtain a new set of opened machines */ /* obtain a new set of spawned machines */ /* reap child processes */ "status=%d, reason=%d\n",
LogFlowFunc ((
"pid %d (%x) was NOT reaped, vrc=%Rrc\n",
/* remove the process if it is not already running */ /* release sets of machines if any */ * Thread function that handles custom events posted using #postEvent(). // create an event queue for the current thread // return the queue to the one who created this thread // signal that we're ready //////////////////////////////////////////////////////////////////////////////// * Takes the current list of registered callbacks of the managed VirtualBox * instance, and calls #handleCallback() for every callback item from the * list, passing the item as an argument. * @note Locks the managed VirtualBox object for reading but leaves the lock * before iterating over callbacks and calling their methods. "the callback event is discarded!\n",
/* We don't need mVirtualBox any more, so release it */ /* Make a copy to release the lock before iterating */ /* We don't need mVirtualBox any more, so release it */