summaryrefslogtreecommitdiff
path: root/src/VBox/Additions/common/VBoxService/VBoxServiceControlExecThread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Additions/common/VBoxService/VBoxServiceControlExecThread.cpp')
-rw-r--r--src/VBox/Additions/common/VBoxService/VBoxServiceControlExecThread.cpp122
1 files changed, 83 insertions, 39 deletions
diff --git a/src/VBox/Additions/common/VBoxService/VBoxServiceControlExecThread.cpp b/src/VBox/Additions/common/VBoxService/VBoxServiceControlExecThread.cpp
index c336eeda8..4692437bc 100644
--- a/src/VBox/Additions/common/VBoxService/VBoxServiceControlExecThread.cpp
+++ b/src/VBox/Additions/common/VBoxService/VBoxServiceControlExecThread.cpp
@@ -1,4 +1,4 @@
-/* $Id: VBoxServiceControlExecThread.cpp 38445 2011-08-12 20:43:24Z vboxsync $ */
+/* $Id: VBoxServiceControlExecThread.cpp $ */
/** @file
* VBoxServiceControlExecThread - Thread for an executed guest process.
*/
@@ -338,60 +338,69 @@ int VBoxServiceControlExecThreadGetOutput(uint32_t uPID, uint32_t uHandleId, uin
int rc = RTCritSectEnter(&g_GuestControlThreadsCritSect);
if (RT_SUCCESS(rc))
{
- const PVBOXSERVICECTRLTHREAD pNode = vboxServiceControlExecThreadGetByPID(uPID);
- if (pNode)
+ const PVBOXSERVICECTRLTHREAD pThread = vboxServiceControlExecThreadGetByPID(uPID);
+ if (pThread)
{
- const PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)pNode->pvData;
+ const PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)pThread->pvData;
AssertPtr(pData);
PVBOXSERVICECTRLEXECPIPEBUF pPipeBuf = NULL;
switch (uHandleId)
{
- case OUTPUT_HANDLE_ID_STDERR: /* StdErr */
+ case OUTPUT_HANDLE_ID_STDERR:
pPipeBuf = &pData->stdErr;
break;
- case OUTPUT_HANDLE_ID_STDOUT: /* StdOut */
+ case OUTPUT_HANDLE_ID_STDOUT:
+ case OUTPUT_HANDLE_ID_STDOUT_DEPRECATED:
pPipeBuf = &pData->stdOut;
break;
default:
- AssertReleaseMsgFailed(("Unknown output handle ID (%u)\n", uHandleId));
+ rc = VERR_NOT_FOUND; /* Handle ID not found! */
break;
}
- AssertPtr(pPipeBuf);
-
-#ifdef DEBUG_andy
- VBoxServiceVerbose(4, "ControlExec: [PID %u]: Getting output from pipe buffer %u ...\n",
- uPID, pPipeBuf->uPipeId);
-#endif
- /* 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. */
- bool fEnabled = VBoxServicePipeBufIsEnabled(pPipeBuf);
- if (fEnabled)
- {
-#ifdef DEBUG_andy
- VBoxServiceVerbose(4, "ControlExec: [PID %u]: Waiting for pipe buffer %u (%ums)\n",
- uPID, pPipeBuf->uPipeId, uTimeout);
-#endif
- rc = VBoxServicePipeBufWaitForEvent(pPipeBuf, uTimeout);
- }
+
if (RT_SUCCESS(rc))
{
- uint32_t cbRead = cbSize;
- rc = VBoxServicePipeBufRead(pPipeBuf, pBuf, cbSize, &cbRead);
+ AssertPtr(pPipeBuf);
+
+ #ifdef DEBUG_andy
+ VBoxServiceVerbose(4, "ControlExec: [PID %u]: Getting output from pipe buffer %u ...\n",
+ uPID, pPipeBuf->uPipeId);
+ #endif
+ /* 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. */
+ bool fEnabled = VBoxServicePipeBufIsEnabled(pPipeBuf);
+ if (fEnabled)
+ {
+ #ifdef DEBUG_andy
+ VBoxServiceVerbose(4, "ControlExec: [PID %u]: Waiting for pipe buffer %u (%ums)\n",
+ uPID, pPipeBuf->uPipeId, uTimeout);
+ #endif
+ rc = VBoxServicePipeBufWaitForEvent(pPipeBuf, uTimeout);
+ }
if (RT_SUCCESS(rc))
{
- if (fEnabled && !cbRead)
- AssertMsgFailed(("[PID %u]: Waited (%ums) for pipe buffer %u (%u bytes left), but nothing read!\n",
- uPID, uTimeout, pPipeBuf->uPipeId, pPipeBuf->cbSize - pPipeBuf->cbOffset));
- if (pcbRead)
- *pcbRead = cbRead;
+ uint32_t cbRead = cbSize; /* Read as much as possible. */
+ rc = VBoxServicePipeBufRead(pPipeBuf, pBuf, cbSize, &cbRead);
+ if (RT_SUCCESS(rc))
+ {
+ if ( !cbRead
+ && fEnabled)
+ {
+ AssertReleaseMsg(!VBoxServicePipeBufIsEnabled(pPipeBuf),
+ ("[PID %u]: Waited (%ums) for active pipe buffer %u (%u size, %u bytes left), but nothing read!\n",
+ uPID, uTimeout, pPipeBuf->uPipeId, pPipeBuf->cbSize, pPipeBuf->cbSize - pPipeBuf->cbOffset));
+ }
+ if (pcbRead)
+ *pcbRead = cbRead;
+ }
+ else
+ VBoxServiceError("ControlExec: [PID %u]: Unable to read from pipe buffer %u, rc=%Rrc\n",
+ uPID, pPipeBuf->uPipeId, rc);
}
- else
- VBoxServiceError("ControlExec: [PID %u]: Unable to read from pipe buffer %u, rc=%Rrc\n",
- uPID, pPipeBuf->uPipeId, rc);
}
}
else
@@ -405,6 +414,38 @@ int VBoxServiceControlExecThreadGetOutput(uint32_t uPID, uint32_t uHandleId, uin
}
+int VBoxServiceControlExecThreadRemove(uint32_t uPID)
+{
+ int rc = RTCritSectEnter(&g_GuestControlThreadsCritSect);
+ if (RT_SUCCESS(rc))
+ {
+ PVBOXSERVICECTRLTHREAD pThread = vboxServiceControlExecThreadGetByPID(uPID);
+ if (pThread)
+ {
+ Assert(pThread->fStarted != pThread->fStopped);
+ if (pThread->fStopped) /* Only shut down stopped threads. */
+ {
+ VBoxServiceVerbose(4, "ControlExec: [PID %u]: Removing thread ... \n",
+ uPID);
+
+ rc = VBoxServiceControlExecThreadShutdown(pThread);
+
+ RTListNodeRemove(&pThread->Node);
+ RTMemFree(pThread);
+ }
+ }
+ else
+ rc = VERR_NOT_FOUND;
+
+ int rc2 = RTCritSectLeave(&g_GuestControlThreadsCritSect);
+ if (RT_SUCCESS(rc))
+ rc = rc2;
+ }
+
+ return rc;
+}
+
+/* Does not do locking, must be done by the caller! */
int VBoxServiceControlExecThreadShutdown(const PVBOXSERVICECTRLTHREAD pThread)
{
AssertPtrReturn(pThread, VERR_INVALID_POINTER);
@@ -433,6 +474,8 @@ int VBoxServiceControlExecThreadShutdown(const PVBOXSERVICECTRLTHREAD pThread)
int VBoxServiceControlExecThreadStartAllowed(bool *pbAllowed)
{
+ AssertPtrReturn(pbAllowed, VERR_INVALID_POINTER);
+
int rc = RTCritSectEnter(&g_GuestControlThreadsCritSect);
if (RT_SUCCESS(rc))
{
@@ -441,7 +484,7 @@ int VBoxServiceControlExecThreadStartAllowed(bool *pbAllowed)
* how many guest processes are started and served already.
*/
bool fLimitReached = false;
- if (g_GuestControlProcsMaxKept) /* If we allow unlimited processes, take a shortcut. */
+ if (g_GuestControlProcsMaxKept) /* If we allow unlimited processes (=0), take a shortcut. */
{
/** @todo Put running/stopped (+ memory alloc) stats into global struct! */
uint32_t uProcsRunning = 0;
@@ -467,7 +510,8 @@ int VBoxServiceControlExecThreadStartAllowed(bool *pbAllowed)
int32_t iProcsLeft = (g_GuestControlProcsMaxKept - uProcsRunning - 1);
if (iProcsLeft < 0)
{
- VBoxServiceVerbose(3, "ControlExec: Maximum running guest processes reached\n");
+ VBoxServiceVerbose(3, "ControlExec: Maximum running guest processes reached (%u)\n",
+ g_GuestControlProcsMaxKept);
fLimitReached = true;
}
else if (uProcsStopped > (uint32_t)iProcsLeft)
@@ -486,7 +530,7 @@ int VBoxServiceControlExecThreadStartAllowed(bool *pbAllowed)
int rc2 = VBoxServiceControlExecThreadShutdown(pNode);
if (RT_FAILURE(rc2))
{
- VBoxServiceError("ControlExec: Unable to shut down thread due to policy, rc=%Rrc", rc2);
+ VBoxServiceError("ControlExec: Unable to shut down thread due to policy, rc=%Rrc\n", rc2);
if (RT_SUCCESS(rc))
rc = rc2;
/* Keep going. */
@@ -496,10 +540,10 @@ int VBoxServiceControlExecThreadStartAllowed(bool *pbAllowed)
RTMemFree(pNode);
pNode = pNext;
+ Assert(uProcsToKill);
uProcsToKill--;
if (!uProcsToKill)
break;
-
}
}
Assert(uProcsToKill == 0);