server.cpp revision 9ed50c4b6a94b633299f224467d7a9f0f941ccef
#
include <
signal.h>
// for the signal handler///////////////////////////////////////////////////////////////////////////// // VirtualBox component instantiation ///////////////////////////////////////////////////////////////////////////// /* implement nsISupports parts of our objects with support for nsIClassInfo */ #
endif /* VBOX_WITH_RESOURCE_USAGE_API *///////////////////////////////////////////////////////////////////////////////// /** Delay before shutting down the VirtualBox server after the last * VirtualBox instance is released, in ms */ ///////////////////////////////////////////////////////////////////////////// * Simple but smart PLEvent wrapper. * @note Instances must be always created with <tt>operator new</tt>! * Posts this event to the given message queue. This method may only be * called once. @note On success, the event will be deleted automatically * after it is delivered and handled. On failure, the event will delete * itself before this method returns! The caller must not delete it in //////////////////////////////////////////////////////////////////////////////// * VirtualBox class factory that destroys the created instance right after * the last reference to it is released by the client, and recreates it again * when necessary (so VirtualBox acts like a singleton object). RTPrintf(
"Informational: VirtualBox object deleted.\n");
/* we overload Release() to guarantee the VirtualBox destructor is * always called on the main thread */ /* the last reference held by clients is being released /* sTimer is null if this call originates from FactoryDestructor()*/ LogFlowFunc((
"Last VirtualBox instance was released.\n"));
LogFlowFunc((
"Scheduling server shutdown in %u ms...\n",
/* make sure the previous timer (if any) is stopped; * otherwise RTTimerStart() will definitely fail. */ "on XPCOM shutdown.\n"));
/* Failed to start the timer, post the shutdown event * manually if not on the main thread already. */ * a) gEventQ is 0 which means either FactoryDestructor() is called * or the IPC/DCONNECT shutdown sequence is initiated by the * XPCOM shutdown routine (NS_ShutdownXPCOM()), which always * happens on the main thread. * b) gEventQ has reported we're on the main thread. This means * that DestructEventHandler() has been called, but another * client was faster and requested VirtualBox again. * In either case, there is nothing to do. * Note: case b) is actually no more valid since we don't * call Release() from DestructEventHandler() in this case * any more. Thus, we assert below. /* called on the main thread */ /* stop accepting GetInstance() requests on other threads during * possible destruction */ /* sInstance is NULL here if it was deleted immediately after * creation due to initialization error. See GetInstance(). */ /* Release the guard reference added in GetInstance() */ /* make it leave the event loop */ /* This condition is quite rare: a new client happened to * connect after this event has been posted to the main queue * but before it started to process it. */ /* A "too late" event is theoretically possible if somebody * manually ended the server after a destruction has been scheduled * and this method was so lucky that it got a chance to run before * the timer was killed. */ /* post a quit event to the main queue */ /* A failure above means we've been already stopped (for example * by Ctrl-C). FactoryDestructor() (NS_ShutdownXPCOM()) * will do the job. Nothing to do. */ /* create a critsect to protect object construction */ /* Either posting a destruction event failed for some reason (most * likely, the quit event has been received before the last release), * or the client has terminated abnormally w/o releasing its * VirtualBox instance (so NS_ShutdownXPCOM() is doing a cleanup). * Release the guard reference we added in GetInstance(). */ LogFlowFunc((
"Process termination requested first. Refusing.\n"));
/* this rv is what CreateInstance() on the client side returns * when the server process stops accepting events. Do the same * here. The client wrapper should attempt to start a new process in * response to a failure from us. */ /* make an extra AddRef to take the full control * on the VirtualBox destruction (see FinalRelease()) */ RTPrintf(
"Informational: VirtualBox object created (rc=%Rhrc).\n",
rv);
/* On failure diring VirtualBox initialization, delete it * immediately on the current thread by releasing all * references in order to properly schedule the server * shutdown. Since the object is fully deleted here, there * is a chance to fix the error and request a new * instantiation before the server terminates. However, * the main reason to maintain the shutdown delay on * failure is to let the front-end completely fetch error * info from a server-side IVirtualBoxErrorInfo object. */ /* On success, make sure the previous timer is stopped to * cancel a scheduled server termination (if any). */ LogFlowFunc((
"Using existing VirtualBox object...\n"));
LogFlowFunc((
"Another client has requested a reference to VirtualBox, canceling destruction...\n"));
/* make sure the previous timer is stopped */ /* Don't be confused that sInstance is of the *ClassFactory type. This is * actually a singleton instance (*ClassFactory inherits the singleton * class; we combined them just for "simplicity" and used "static" for * factory methods. *ClassFactory here is necessary for a couple of extra //////////////////////////////////////////////////////////////////////////////// * Enhanced module component information structure. * nsModuleComponentInfo lacks the factory construction callback, here we add * it. This callback is called straight after a nsGenericFactory instance is * successfully created in RegisterSelfComponents. /** standard module component information */ /** (optional) Factory Construction Callback */ ///////////////////////////////////////////////////////////////////////////// * Helper function to register self components upon start-up * of the out-of-proc server. /* skip components w/o a constructor */ /* create a new generic factory for a component and register it */ ///////////////////////////////////////////////////////////////////////////// /* post a force quit event to the queue */ // The ugly casts are necessary because the PR_CreateProcessDetached has // a const array of writable strings as a parameter. It won't write. */ char *
args[
1 +
1 +
2 +
1];
// Use a pipe to determine when the daemon process is in the position // to actually process requests. The daemon will write "READY" to the pipe. // Close the child end of the pipe to make it the only owner of the // file descriptor, so that unexpected closing can be detected. * Initialize the VBox runtime without loading /* --automate mode means we are started by XPCOM on * demand. Daemonize ourselves and activate /* --auto-shutdown mode means we're already daemonized. */ NULL,
// registration function NULL,
// deregistration function RTMsgError(
"Failed to get component registrar! (rc=%Rhrc)",
rc);
RTMsgError(
"Failed to register server components! (rc=%Rhrc)",
rc);
/* get the main thread's event queue (afaik, the dconnect service always * gets created upon XPCOM startup, so it will use the main (this) * thread's event queue to receive IPC events) */ RTMsgError(
"Failed to get the main event queue! (rc=%Rhrc)",
rc);
LogFlowFunc((
"Failed to register the server name (rc=%Rhrc (%08X))!\n" "Is another server already running?\n",
rc,
rc));
RTMsgError(
"Failed to register the server name \"%s\" (rc=%Rhrc)!\n" "Is another server already running?\n",
/* setup signal handling to convert some signals to a quit event */ for (
int i =
iSize; i > 0; i--)
"All rights reserved.\n");
RTPrintf(
"\nStarting event loop....\n[send TERM signal to quit]\n");
/* now we're ready, signal the parent process */ /* close writing end of the pipe, its job is done */ RTPrintf(
"\nStarting event loop....\n[press Ctrl-C to quit]\n");
// Increase the file table size to 10240 or as high as possible. RTPrintf(
"WARNING: failed to increase file descriptor limit. (%d)\n",
errno);
RTPrintf(
"WARNING: failed to obtain per-process file-descriptor limit (%d).\n",
errno);
/* stop accepting new events. Clients that happen to resolve our * name and issue a CreateInstance() request after this point will * get NS_ERROR_ABORT once we handle the remaining messages. As a * result, they should try to start a new server process. */ /* unregister ourselves. After this point, clients will start a new * process because they won't be able to resolve the server name.*/ /* process any remaining events. These events may include * CreateInstance() requests received right before we called * StopAcceptingEvents() above. We will detect this case below, * restore gKeepRunning and continue to serve. */ while (0);
// this scopes the nsCOMPtrs /* no nsCOMPtrs are allowed to be alive when you call com::Shutdown(). */ RTPrintf(
"XPCOM server has shutdown.\n");