server_module.cpp revision c12e254c1838a1b167dd65cf40b90067f136d8ca
/** @file
*
* XPCOM server process helper module implementation functions
*/
/*
* Copyright (C) 2006-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#ifdef RT_OS_OS2
# include <prproces.h>
#endif
#include <nsMemory.h>
#include <nsString.h>
#include <nsCOMPtr.h>
#include <nsIFile.h>
#include <nsIGenericFactory.h>
#include <nsIServiceManagerUtils.h>
#include <nsICategoryManager.h>
#include <nsDirectoryServiceDefs.h>
#include <ipcIService.h>
#include <ipcIDConnectService.h>
#include <ipcCID.h>
#include <ipcdclient.h>
#include "prio.h"
#include "prproces.h"
// official XPCOM headers don't define it yet
#define IPC_DCONNECTSERVICE_CONTRACTID \
// generated file
#include <VirtualBox_XPCOM.h>
#include "server.h"
#include "Logging.h"
#include <string.h>
#if defined(RT_OS_SOLARIS)
# include <sys/systeminfo.h>
#endif
/// @todo move this to RT headers (and use them in MachineImpl.cpp as well)
#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
#define HOSTSUFF_EXE ".exe"
#else /* !RT_OS_WINDOWS */
#define HOSTSUFF_EXE ""
#endif /* !RT_OS_WINDOWS */
/** Name of the server executable. */
enum
{
/** Amount of time to wait for the server to establish a connection, ms */
VBoxSVC_Timeout = 30000,
/** How often to perform a connection check, ms */
VBoxSVC_WaitSlice = 100
};
/**
* Full path to the VBoxSVC executable.
*/
static char VBoxSVCPath[RTPATH_MAX];
static bool IsVBoxSVCPathSet = false;
/*
* The following macros define the method necessary to provide a list of
* interfaces implemented by the VirtualBox component. Note that this must be
* in sync with macros used for VirtualBox in server.cpp for the same purpose.
*/
static nsresult vboxsvcSpawnDaemon(void)
{
// The ugly casts are necessary because the PR_CreateProcessDetached has
// a const array of writable strings as a parameter. It won't write. */
// 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.
goto end;
attr = PR_NewProcessAttr();
if (!attr)
goto end;
goto end;
if (!devNull)
goto end;
goto end;
// Close the child end of the pipe to make it the only owner of the
// file descriptor, so that unexpected closing can be detected.
char msg[10];
{
/* If several clients start VBoxSVC simultaneously only one can
* succeed. So treat this as success as well. */
goto end;
}
end:
if (readable)
if (writable)
if (attr)
return rv;
}
/**
* VirtualBox component constructor.
*
* This constructor is responsible for starting the VirtualBox server
* process, connecting to it, and redirecting the constructor request to the
* VirtualBox component defined on the server.
*/
static NS_IMETHODIMP
void **aResult)
{
int vrc = VINF_SUCCESS;
do
{
{
break;
}
if (!IsVBoxSVCPathSet)
{
/* Get the directory containing XPCOM components -- the VBoxSVC
* executable is expected in the parent directory. */
if (NS_SUCCEEDED(rc))
{
if (NS_SUCCEEDED(rc))
{
rc = NS_ERROR_FAILURE);
#if defined(RT_OS_SOLARIS) && defined(VBOX_WITH_HARDENING)
char achKernArch[128];
if (cbKernArch > 0)
{
IsVBoxSVCPathSet = true;
}
else
#else
IsVBoxSVCPathSet = true;
#endif
}
}
break;
}
break;
/* connect to the VBoxSVC server process */
bool startedOnce = false;
unsigned timeLeft = VBoxSVC_Timeout;
do
{
{
startedOnce = true;
rc = vboxsvcSpawnDaemon();
break;
/* wait for the server process to establish a connection */
do
{
if (NS_SUCCEEDED(rc))
break;
if (timeLeft <= VBoxSVC_WaitSlice)
{
timeLeft = 0;
break;
}
}
while (1);
if (!timeLeft)
{
break;
}
}
break;
if (NS_SUCCEEDED(rc))
break;
/* It's possible that the server gets shut down after we
* successfully resolve the server name but before it
* receives our CreateInstance() request. So, check for the
* name again, and restart the cycle if it fails. */
if (!startedOnce)
{
if (NS_SUCCEEDED(rc2))
break;
LogFlowFunc (("Server seems to have terminated before "
"receiving our request. Will try again.\n"));
}
else
break;
}
while (1);
}
while (0);
return rc;
}
#if 0
/// @todo not really necessary for the moment
/**
*
* @param aCompMgr
* @param aPath
* @param aLoaderStr
* @param aType
* @param aInfo
*
* @return
*/
static NS_IMETHODIMP
const char *aLoaderStr,
const char *aType,
const nsModuleComponentInfo *aInfo)
{
LogFlowFunc (("aPath=%s, aTarget=%s, aLoaderStr=%s, aType=%s\n",
return rc;
}
#endif
/**
* Component definition table.
* Lists all components defined in this module.
*/
static const nsModuleComponentInfo components[] =
{
{
"VirtualBox component", // description
VirtualBoxConstructor, // constructor function
NULL, // deregistration function
NULL, // destructor function
/// @todo
NULL, // language helper
/// @todo
}
};