VBoxServiceControlExecThread.cpp revision 599104d38a98f53d08be0aa687444c6099983c38
/* $Id$ */
/** @file
* VBoxServiceControlExecThread - Thread for an executed guest process.
*/
/*
* Copyright (C) 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.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <iprt/semaphore.h>
#include "VBoxServicePipeBuf.h"
#include "VBoxServiceControlExecThread.h"
extern RTLISTNODE g_GuestControlExecThreads;
/**
* Allocates and gives back a thread data struct which then can be used by the worker thread.
* Needs to be freed with VBoxServiceControlExecDestroyThreadData().
*
* @return IPRT status code.
* @param pThread The thread's handle to allocate the data for.
* @param u32ContextID The context ID bound to this request / command.
* @param pszCmd Full qualified path of process to start (without arguments).
* @param uFlags Process execution flags.
* @param pszArgs String of arguments to pass to the process to start.
* @param uNumArgs Number of arguments specified in pszArgs.
* @param pszEnv String of environment variables ("FOO=BAR") to pass to the process
* to start.
* @param cbEnv Size (in bytes) of environment variables.
* @param uNumEnvVars Number of environment variables specified in pszEnv.
* @param pszUser User name (account) to start the process under.
* @param pszPassword Password of specified user name (account).
* @param uTimeLimitMS Time limit (in ms) of the process' life time.
*/
{
/* General stuff. */
/* ClientID will be assigned when thread is started! */
/* Specific stuff. */
PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)RTMemAlloc(sizeof(VBOXSERVICECTRLTHREADDATAEXEC));
return VERR_NO_MEMORY;
pData->uNumEnvVars = 0;
/* Prepare argument list. */
/* Did we get the same result? */
if (RT_SUCCESS(rc))
{
/* Prepare environment list. */
if (uNumEnvVars)
{
uint32_t i = 0;
{
/* sanity check */
if (i >= uNumEnvVars)
{
break;
}
if (cbStr < 0)
{
break;
}
}
}
/* Adjust time limit value. */
|| uTimeLimitMS == 0)
/* Init buffers. */
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
}
}
if (RT_FAILURE(rc))
{
}
else
{
}
return rc;
}
/**
* Frees an allocated thread data structure along with all its allocated parameters.
*
* @param pData Pointer to thread data to free.
*/
{
if (pData)
{
if (pData->uNumEnvVars)
{
}
}
}
/**
* Finds a (formerly) started process given by its PID.
* Internal function, does not do locking -- this must be done from the caller function!
*
* @return PVBOXSERVICECTRLTHREAD Process structure if found, otherwise NULL.
* @param uPID PID to search for.
*/
{
{
{
return pNode;
}
}
return NULL;
}
/**
* Injects input to a specified running process.
*
* @return IPRT status code.
* @param uPID PID of process to set the input for.
* @param fPendingClose Flag indicating whether this is the last input block sent to the process.
* @param pBuf Pointer to a buffer containing the actual input data.
* @param cbSize Size (in bytes) of the input buffer data.
* @param pcbWritten Pointer to number of bytes written to the process. Optional.
*/
{
if (RT_SUCCESS(rc))
{
if (pNode)
{
{
/*
* Feed the data to the pipe.
*/
if (pcbWritten)
*pcbWritten = cbWritten;
}
else
{
/* If input buffer is not enabled anymore we cannot handle that data ... */
rc = VERR_BAD_PIPE;
}
}
else
}
return rc;
}
/**
*
* @return IPRT status code.
* @param uPID PID of process to retrieve the output from.
* @param uHandleId Stream ID (stdout = 0, stderr = 2) to get the output from.
* @param uTimeout Timeout (in ms) to wait for output becoming available.
* @param pBuf Pointer to a pre-allocated buffer to store the output.
* @param cbSize Size (in bytes) of the pre-allocated buffer.
* @param pcbRead Pointer to number of bytes read. Optional.
*/
{
if (RT_SUCCESS(rc))
{
if (pNode)
{
switch (uHandleId)
{
case OUTPUT_HANDLE_ID_STDERR: /* StdErr */
break;
case OUTPUT_HANDLE_ID_STDOUT: /* StdOut */
default:
break;
}
/* If the stdout pipe buffer is enabled (that is, still could be filled by a running
* process) wait for the signal to arrive so that we don't return without any actual
* data read. */
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
if (pcbRead)
}
}
}
else
if (RT_SUCCESS(rc))
}
return rc;
}
/**
* Gracefully shuts down all process execution threads.
*
*/
void VBoxServiceControlExecThreadsShutdown(void)
{
if (RT_SUCCESS(rc))
{
/* Signal all threads that we want to shutdown. */
/* Wait for threads to shutdown. */
{
{
/* Wait a bit ... */
if (RT_FAILURE(rc2))
}
/* Destroy thread specific data. */
{
break;
default:
break;
}
}
/* Finally destroy thread list. */
while (pNode)
{
if (fLast)
break;
}
if (RT_SUCCESS(rc))
}
}