Changeset 38113 in vbox
- Timestamp:
- Jul 22, 2011 1:57:35 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 73065
- Location:
- trunk/src/VBox/Additions/common/VBoxService
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
r36745 r38113 59 59 /** The current verbosity level. */ 60 60 int g_cVerbosity = 0; 61 /** Critical section for (debug) logging. */ 62 #ifdef DEBUG 63 RTCRITSECT g_csLog; 64 #endif 61 65 /** The default service interval (the -i | --interval) option). */ 62 66 uint32_t g_DefaultInterval = 0; … … 217 221 void VBoxServiceVerbose(int iLevel, const char *pszFormat, ...) 218 222 { 219 if (iLevel <= g_cVerbosity) 220 { 221 RTStrmPrintf(g_pStdOut, "%s: ", g_pszProgName); 222 va_list va; 223 va_start(va, pszFormat); 224 RTStrmPrintfV(g_pStdOut, pszFormat, va); 225 va_end(va); 226 va_start(va, pszFormat); 227 LogRel(("%s: %N", g_pszProgName, pszFormat, &va)); 228 va_end(va); 229 } 223 #ifdef DEBUG 224 int rc = RTCritSectEnter(&g_csLog); 225 if (RT_SUCCESS(rc)) 226 { 227 #endif 228 if (iLevel <= g_cVerbosity) 229 { 230 #ifdef DEBUG 231 const char *pszThreadName = RTThreadSelfName(); 232 AssertPtr(pszThreadName); 233 RTStrmPrintf(g_pStdOut, "%s [%s]: ", 234 g_pszProgName, pszThreadName); 235 #else 236 RTStrmPrintf(g_pStdOut, "%s: ", g_pszProgName); 237 #endif 238 va_list va; 239 va_start(va, pszFormat); 240 RTStrmPrintfV(g_pStdOut, pszFormat, va); 241 va_end(va); 242 va_start(va, pszFormat); 243 LogRel(("%s: %N", g_pszProgName, pszFormat, &va)); 244 va_end(va); 245 } 246 #ifdef DEBUG 247 int rc2 = RTCritSectLeave(&g_csLog); 248 if (RT_SUCCESS(rc)) 249 rc = rc2; 250 } 251 #endif 230 252 } 231 253 … … 580 602 return RTMsgInitFailure(rc); 581 603 g_pszProgName = RTPathFilename(argv[0]); 604 #ifdef DEBUG 605 rc = RTCritSectInit(&g_csLog); 606 AssertRC(rc); 607 #endif 582 608 583 609 #ifdef VBOXSERVICE_TOOLBOX … … 851 877 852 878 VBoxServiceVerbose(0, "Ended.\n"); 879 880 #ifdef DEBUG 881 RTCritSectDelete(&g_csLog); 882 #endif 853 883 return rcExit; 854 884 } -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp
r38085 r38113 191 191 192 192 /** 193 * Handle pending output data/error on st andard out or standard error.193 * Handle pending output data/error on stdout or stderr. 194 194 * 195 195 * @return IPRT status code. … … 206 206 AssertPtrReturn(pBuf, VERR_INVALID_POINTER); 207 207 208 #ifdef DEBUG209 VBoxServiceVerbose(4, "ControlExec: HandleOutputEvent: fPollEvt=%#x, uHandle=%u\n",210 fPollEvt, uHandleId);211 #endif212 213 208 /* 214 209 * Try drain the pipe before acting on any errors. … … 224 219 rc = VBoxServicePipeBufWriteToBuf(pBuf, abBuf, 225 220 cbRead, false /* Pending close */, &cbWritten); 221 #ifdef DEBUG_andy 222 VBoxServiceVerbose(4, "ControlExec: Written output event [%u %u], cbRead=%u, cbWritten=%u, rc=%Rrc, uHandleId=%u, fPollEvt=%#x\n", 223 pBuf->uPID, pBuf->uPipeId, cbRead, cbWritten, rc, uHandleId, fPollEvt); 224 #endif 226 225 if (RT_SUCCESS(rc)) 227 226 { … … 257 256 PRTPIPE phNotificationPipeR, PRTPIPE phInputPipeW) 258 257 { 259 #ifdef DEBUG 258 #ifdef DEBUG_andy 260 259 VBoxServiceVerbose(4, "ControlExec: HandleStdInputNotify\n"); 261 260 #endif … … 317 316 AssertPtr(pData); 318 317 319 /* Assign PID to thread data. */ 320 pData->uPID = hProcess; 318 /* 319 * Assign PID to thread data. 320 * Also check if there already was a thread with the same PID and shut it down -- otherwise 321 * the first (stale) entry will be found and we get really weird results! 322 */ 323 rc = VBoxServiceControlExecThreadAssignPID(pData, hProcess); 324 if (RT_FAILURE(rc)) 325 { 326 VBoxServiceError("ControlExec: Unable to assign PID to new thread, rc=%Rrc\n", rc); 327 return rc; 328 } 321 329 322 330 /* … … 324 332 * and that it's now OK to send input to the process. 325 333 */ 326 VBoxServiceVerbose(3, "ControlExec: Process started: PID=%u, CID=%u, User=%s\n",334 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Process started, CID=%u, User=%s\n", 327 335 pData->uPID, pThread->uContextID, pData->pszUser); 328 336 rc = VbglR3GuestCtrlExecReportStatus(pThread->uClientID, pThread->uContextID, … … 349 357 if (RT_SUCCESS(rc2)) 350 358 { 351 VBoxServiceVerbose(4, "ControlExec: RTPollNoResume idPollHnd=%u\n", idPollHnd); 359 /*VBoxServiceVerbose(4, "ControlExec: [PID %u}: RTPollNoResume idPollHnd=%u\n", 360 pData->uPID, idPollHnd);*/ 352 361 switch (idPollHnd) 353 362 { … … 370 379 371 380 case VBOXSERVICECTRLPIPEID_STDOUT: 381 #ifdef DEBUG 382 VBoxServiceVerbose(4, "ControlExec: [PID %u]: StdOut fPollEvt=%#x\n", 383 pData->uPID, fPollEvt); 384 #endif 372 385 rc = VBoxServiceControlExecProcHandleOutputEvent(hPollSet, fPollEvt, phStdOutR, 373 386 VBOXSERVICECTRLPIPEID_STDOUT, &pData->stdOut); 387 // TEST!!! 388 VBoxServicePipeBufIsEnabled(&pData->stdOut); 374 389 break; 375 390 376 391 case VBOXSERVICECTRLPIPEID_STDERR: 392 #ifdef DEBUG 393 VBoxServiceVerbose(4, "ControlExec: [PID %u]: StdErr: fPollEvt=%#x\n", 394 pData->uPID, fPollEvt); 395 #endif 377 396 rc = VBoxServiceControlExecProcHandleOutputEvent(hPollSet, fPollEvt, phStdErrR, 378 397 VBOXSERVICECTRLPIPEID_STDERR, &pData->stdErr); … … 380 399 381 400 default: 382 AssertMsgFailed(("idPollHnd=%u fPollEvt=%#x\n", idPollHnd, fPollEvt)); 401 AssertMsgFailed(("PID=%u idPollHnd=%u fPollEvt=%#x\n", 402 pData->uPID, idPollHnd, fPollEvt)); 383 403 break; 384 404 } … … 428 448 if (cMsElapsed >= cMsTimeout) 429 449 { 430 VBoxServiceVerbose(3, "ControlExec: Process timed out (%ums elapsed > %ums timeout), killing ...", cMsElapsed, cMsTimeout); 450 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Timed out (%ums elapsed > %ums timeout), killing ...", 451 pData->uPID, cMsElapsed, cMsTimeout); 431 452 432 453 fProcessTimedOut = true; … … 463 484 if (MsProcessKilled == UINT64_MAX) 464 485 { 465 VBoxServiceVerbose(3, "ControlExec: Process (PID=%u) is still alive and not killed yet\n",486 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Is still alive and not killed yet\n", 466 487 pData->uPID); 467 488 … … 473 494 for (size_t i = 0; i < 10; i++) 474 495 { 475 VBoxServiceVerbose(4, "ControlExec: Kill attempt %d/10: Waiting for process (PID=%u)exit ...\n",476 i + 1, pData->uPID);496 VBoxServiceVerbose(4, "ControlExec: [PID %u]: Kill attempt %d/10: Waiting to exit ...\n", 497 pData->uPID, i + 1); 477 498 rc2 = RTProcWait(hProcess, RTPROCWAIT_FLAGS_NOBLOCK, &ProcessStatus); 478 499 if (RT_SUCCESS(rc2)) 479 500 { 480 VBoxServiceVerbose(4, "ControlExec: Kill attempt %d/10: Process (PID=%u) exited\n",481 i + 1, pData->uPID);501 VBoxServiceVerbose(4, "ControlExec: [PID %u]: Kill attempt %d/10: Exited\n", 502 pData->uPID, i + 1); 482 503 fProcessAlive = false; 483 504 break; … … 485 506 if (i >= 5) 486 507 { 487 VBoxServiceVerbose(4, "ControlExec: Kill attempt %d/10: Try to terminate (PID=%u)...\n",488 i + 1, pData->uPID);508 VBoxServiceVerbose(4, "ControlExec: [PID %u]: Kill attempt %d/10: Trying to terminate ...\n", 509 pData->uPID, i + 1); 489 510 RTProcTerminate(hProcess); 490 511 } … … 493 514 494 515 if (fProcessAlive) 495 VBoxServiceVerbose(3, "ControlExec: Process (PID=%u) could not be killed\n", pData->uPID);516 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Could not be killed\n", pData->uPID); 496 517 } 497 518 498 519 /* 499 * If we don't have a client problem (RT_FAILURE(rc) we'll reply to the520 * If we don't have a client problem (RT_FAILURE(rc)) we'll reply to the 500 521 * clients exec packet now. 501 522 */ … … 516 537 if ( fProcessTimedOut && !fProcessAlive && MsProcessKilled != UINT64_MAX) 517 538 { 518 VBoxServiceVerbose(3, "ControlExec: Process timed out and got killed\n"); 539 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Timed out and got killed\n", 540 pData->uPID); 519 541 uStatus = PROC_STS_TOK; 520 542 } 521 543 else if (fProcessTimedOut && fProcessAlive && MsProcessKilled != UINT64_MAX) 522 544 { 523 VBoxServiceVerbose(3, "ControlExec: Process timed out and did *not* get killed\n"); 545 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Timed out and did *not* get killed\n", 546 pData->uPID); 524 547 uStatus = PROC_STS_TOA; 525 548 } 526 549 else if (pThread->fShutdown && (fProcessAlive || MsProcessKilled != UINT64_MAX)) 527 550 { 528 VBoxServiceVerbose(3, "ControlExec: Process got terminated because system/service is about to shutdown\n"); 551 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Got terminated because system/service is about to shutdown\n", 552 pData->uPID); 529 553 uStatus = PROC_STS_DWN; /* Service is stopping, process was killed. */ 530 554 uFlags = pData->uFlags; /* Return handed-in execution flags back to the host. */ … … 532 556 else if (fProcessAlive) 533 557 { 534 VBoxServiceError("ControlExec: Process is alive when it should not!\n"); 558 VBoxServiceError("ControlExec: [PID %u]: Is alive when it should not!\n", 559 pData->uPID); 535 560 } 536 561 else if (MsProcessKilled != UINT64_MAX) 537 562 { 538 VBoxServiceError("ControlExec: Process has been killed when it should not!\n"); 563 VBoxServiceError("ControlExec: [PID %u]: Has been killed when it should not!\n", 564 pData->uPID); 539 565 } 540 566 else if (ProcessStatus.enmReason == RTPROCEXITREASON_NORMAL) 541 567 { 542 VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_NORMAL (%u)\n",543 ProcessStatus.iStatus);568 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Ended with RTPROCEXITREASON_NORMAL (%u)\n", 569 pData->uPID, ProcessStatus.iStatus); 544 570 545 571 uStatus = PROC_STS_TEN; … … 548 574 else if (ProcessStatus.enmReason == RTPROCEXITREASON_SIGNAL) 549 575 { 550 VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_SIGNAL (%u)\n",551 ProcessStatus.iStatus);576 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Ended with RTPROCEXITREASON_SIGNAL (%u)\n", 577 pData->uPID, ProcessStatus.iStatus); 552 578 553 579 uStatus = PROC_STS_TES; … … 556 582 else if (ProcessStatus.enmReason == RTPROCEXITREASON_ABEND) 557 583 { 558 VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_ABEND (%u)\n",559 ProcessStatus.iStatus);584 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Ended with RTPROCEXITREASON_ABEND (%u)\n", 585 pData->uPID, ProcessStatus.iStatus); 560 586 561 587 uStatus = PROC_STS_TEA; … … 563 589 } 564 590 else 565 { 566 VBoxServiceError("ControlExec: Process has reached an undefined status!\n"); 567 } 568 569 VBoxServiceVerbose(3, "ControlExec: Process ended: PID=%u, CID=%u, Status=%u, Flags=%u\n", 591 VBoxServiceError("ControlExec: [PID %u]: Reached an undefined state!\n", 592 pData->uPID); 593 594 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Ended, CID=%u, Status=%u, Flags=%u\n", 570 595 pData->uPID, pThread->uContextID, uStatus, uFlags); 571 596 rc = VbglR3GuestCtrlExecReportStatus(pThread->uClientID, pThread->uContextID, 572 597 pData->uPID, uStatus, uFlags, 573 598 NULL /* pvData */, 0 /* cbData */); 574 VBoxServiceVerbose(3, "ControlExec: Process loop ended with rc=%Rrc\n", rc); 599 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Process loop ended with rc=%Rrc\n", 600 pData->uPID, rc); 575 601 576 602 /* … … 580 606 if (g_cVerbosity >= 5) 581 607 { 582 VBoxServiceVerbose(5, " StdOut of process (PID %u):\n", pData->uPID);608 VBoxServiceVerbose(5, "[PID %u]: StdOut:\n", pData->uPID); 583 609 584 610 uint8_t szBuf[_64K]; … … 589 615 && cbRead) 590 616 { 591 RTStrmWrite(g_pStdOut, szBuf, cbRead);592 617 cbOffset += cbRead; 593 618 if (!cbLeft) … … 599 624 } 600 625 else 601 VBoxServiceError("ControlExec: Process loop failed with rc=%Rrc\n", rc); 626 VBoxServiceError("ControlExec: [PID %u]: Loop failed with rc=%Rrc\n", 627 pData->uPID, rc); 602 628 return rc; 603 629 } … … 883 909 uProcFlags |= RTPROC_FLAGS_SERVICE; 884 910 #ifdef DEBUG 885 VBoxServiceVerbose(3, "Co mmand: %s\n", szExecExp);911 VBoxServiceVerbose(3, "ControlExec: Command: %s\n", szExecExp); 886 912 for (size_t i = 0; papszArgsExp[i]; i++) 887 VBoxServiceVerbose(3, " \targv[%ld]: %s\n", i, papszArgsExp[i]);913 VBoxServiceVerbose(3, "ControlExec:\targv[%ld]: %s\n", i, papszArgsExp[i]); 888 914 #endif 889 915 /* Do normal execution. */ … … 1020 1046 * So, NIL the handles to avoid closing them again. 1021 1047 */ 1022 if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, 0 /* stdin */, NULL)))1048 if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_WRITABLE, NULL))) 1023 1049 pData->pipeStdInW = NIL_RTPIPE; 1024 if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, 1 /* stdout */, NULL))) 1050 if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_INPUT_NOTIFY, NULL))) 1051 pData->stdIn.hNotificationPipeR = NIL_RTPIPE; 1052 if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, VBOXSERVICECTRLPIPEID_STDOUT, NULL))) 1025 1053 hStdOutR = NIL_RTPIPE; 1026 if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, 2 /* stderr */, NULL)))1054 if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, VBOXSERVICECTRLPIPEID_STDERR, NULL))) 1027 1055 hStdErrR = NIL_RTPIPE; 1028 1056 } … … 1041 1069 } 1042 1070 RTPollSetDestroy(hPollSet); 1071 RTPipeClose(pData->stdIn.hNotificationPipeR); 1043 1072 } 1044 1073 RTPipeClose(hStdErrR); … … 1056 1085 1057 1086 VbglR3GuestCtrlDisconnect(pThread->uClientID); 1058 VBoxServiceVerbose(3, "ControlExec: Thread of process \"%s\" (PID: %u)ended with rc=%Rrc\n",1059 pData-> pszCmd, pData->uPID, rc);1087 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Thread of process \"%s\" ended with rc=%Rrc\n", 1088 pData->uPID, pData->pszCmd, rc); 1060 1089 1061 1090 /* … … 1122 1151 if (RT_SUCCESS(rc)) 1123 1152 { 1153 static uint32_t uCtrlExecThread = 0; 1154 char szThreadName[32]; 1155 if (!RTStrPrintf(szThreadName, sizeof(szThreadName), "controlexec%ld", uCtrlExecThread++)) 1156 AssertMsgFailed(("Unable to create unique control exec thread name!\n")); 1157 1124 1158 rc = RTThreadCreate(&pThread->Thread, VBoxServiceControlExecThread, 1125 1159 (void *)(PVBOXSERVICECTRLTHREAD*)pThread, 0, 1126 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Exec");1160 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, szThreadName); 1127 1161 if (RT_FAILURE(rc)) 1128 1162 { … … 1135 1169 1136 1170 /* Wait for the thread to initialize. */ 1137 RTThreadUserWait(pThread->Thread, 60 * 1000 );1171 RTThreadUserWait(pThread->Thread, 60 * 1000 /* 60 seconds max. */); 1138 1172 if (pThread->fShutdown) 1139 1173 { … … 1220 1254 else 1221 1255 VBoxServiceError("ControlExec: Failed to retrieve exec start command! Error: %Rrc\n", rc); 1222 VBoxServiceVerbose(3, "ControlExec: VBoxServiceControlExecHandleCmdStartProcess returned with %Rrc\n", rc);1223 1256 return rc; 1224 1257 } … … 1256 1289 if (RT_FAILURE(rc)) 1257 1290 { 1258 VBoxServiceError("ControlExec: Failed to retrieve exec input command! Error: %Rrc\n", rc); 1291 VBoxServiceError("ControlExec: [PID %u]: Failed to retrieve exec input command! Error: %Rrc\n", 1292 uPID, rc); 1259 1293 } 1260 1294 else if (cbSize > cbMaxBufSize) 1261 1295 { 1262 VBoxServiceError("ControlExec: Maximum input buffer size is too small! cbSize=%u, cbMaxBufSize=%u\n",1263 cbSize, cbMaxBufSize);1296 VBoxServiceError("ControlExec: [PID %u]: Maximum input buffer size is too small! cbSize=%u, cbMaxBufSize=%u\n", 1297 uPID, cbSize, cbMaxBufSize); 1264 1298 rc = VERR_INVALID_PARAMETER; 1265 1299 } … … 1273 1307 { 1274 1308 fPendingClose = true; 1275 VBoxServiceVerbose(4, "ControlExec: Got last input block (PID %u)of size %u ...\n",1309 VBoxServiceVerbose(4, "ControlExec: [PID %u]: Got last input block of size %u ...\n", 1276 1310 uPID, cbSize); 1277 1311 } … … 1279 1313 rc = VBoxServiceControlExecThreadSetInput(uPID, fPendingClose, pabBuffer, 1280 1314 cbSize, &cbWritten); 1281 VBoxServiceVerbose(4, "ControlExec: Written input (PID %u):rc=%Rrc, uFlags=0x%x, fPendingClose=%d, cbSize=%u, cbWritten=%u\n",1315 VBoxServiceVerbose(4, "ControlExec: [PID %u]: Written input, rc=%Rrc, uFlags=0x%x, fPendingClose=%d, cbSize=%u, cbWritten=%u\n", 1282 1316 uPID, rc, uFlags, fPendingClose, cbSize, cbWritten); 1283 1317 if (RT_SUCCESS(rc)) … … 1311 1345 Assert(uStatus > INPUT_STS_UNDEFINED); 1312 1346 1313 VBoxServiceVerbose(3, "ControlExec: Input processed (PID %u), Status=%u,Flags=0x%x, cbWritten=%u\n",1347 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Input processed, uStatus=%u, uFlags=0x%x, cbWritten=%u\n", 1314 1348 uPID, uStatus, uFlags, cbWritten); 1315 1349 … … 1321 1355 1322 1356 if (RT_FAILURE(rc)) 1323 VBoxServiceError("ControlExec: Failed to report input status! Error: %Rrc\n", rc); 1357 VBoxServiceError("ControlExec: [PID %u]: Failed to report input status! Error: %Rrc\n", 1358 uPID, rc); 1324 1359 return rc; 1325 1360 } … … 1345 1380 if (RT_SUCCESS(rc)) 1346 1381 { 1347 uint32_t cbRead ;1382 uint32_t cbRead = 0; 1348 1383 uint8_t *pBuf = (uint8_t*)RTMemAlloc(_64K); 1349 1384 if (pBuf) … … 1352 1387 pBuf, _64K /* cbSize */, &cbRead); 1353 1388 if (RT_SUCCESS(rc)) 1354 { 1355 VBoxServiceVerbose(3, "ControlExec: Got output (PID %u), read=%u, handle=%u, flags=%u\n", 1389 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Got output, cbRead=%u, uHandle=%u, uFlags=%u\n", 1356 1390 uPID, cbRead, uHandleID, uFlags); 1357 1358 /* Note: Since the context ID is unique the request *has* to be completed here,1359 * regardless whether we got data or not! Otherwise the progress object1360 * on the host never will get completed! */1361 /* cbRead now contains actual size. */1362 rc = VbglR3GuestCtrlExecSendOut(u32ClientId, uContextID, uPID, uHandleID, uFlags,1363 pBuf, cbRead);1364 }1365 1391 else 1366 VBoxServiceError("ControlExec: Failed to retrieve output (PID %u), rc=%Rrc\n", 1367 uPID, rc); 1392 VBoxServiceError("ControlExec: [PID %u]: Failed to retrieve output, uHandle=%u, rc=%Rrc\n", 1393 uPID, uHandleID, rc); 1394 1395 /* Note: Since the context ID is unique the request *has* to be completed here, 1396 * regardless whether we got data or not! Otherwise the progress object 1397 * on the host never will get completed! */ 1398 /* cbRead now contains actual size. */ 1399 int rc2 = VbglR3GuestCtrlExecSendOut(u32ClientId, uContextID, uPID, uHandleID, uFlags, 1400 pBuf, cbRead); 1401 if (RT_SUCCESS(rc)) 1402 rc = rc2; 1368 1403 RTMemFree(pBuf); 1369 1404 } … … 1371 1406 rc = VERR_NO_MEMORY; 1372 1407 } 1373 else 1374 VBoxServiceError("ControlExec: Failed to retrieve exec output command! Error: %Rrc\n", rc); 1375 return rc; 1376 } 1377 1408 1409 if (RT_FAILURE(rc)) 1410 VBoxServiceError("ControlExec: [PID %u]: Failed to handle output command! Error: %Rrc\n", 1411 uPID, rc); 1412 return rc; 1413 } 1414 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExecThread.cpp
r38085 r38113 36 36 extern RTCRITSECT g_GuestControlExecThreadsCritSect; 37 37 38 const PVBOXSERVICECTRLTHREAD vboxServiceControlExecThreadGetByPID(uint32_t uPID); 38 39 39 40 /** … … 134 135 135 136 /* Init buffers. */ 136 rc = VBoxServicePipeBufInit(&pData->stdOut, false /*fNeedNotificationPipe*/); 137 rc = VBoxServicePipeBufInit(&pData->stdOut, VBOXSERVICECTRLPIPEID_STDOUT, 138 false /*fNeedNotificationPipe*/); 137 139 if (RT_SUCCESS(rc)) 138 140 { 139 rc = VBoxServicePipeBufInit(&pData->stdErr, false /*fNeedNotificationPipe*/); 141 rc = VBoxServicePipeBufInit(&pData->stdErr, VBOXSERVICECTRLPIPEID_STDERR, 142 false /*fNeedNotificationPipe*/); 140 143 if (RT_SUCCESS(rc)) 141 rc = VBoxServicePipeBufInit(&pData->stdIn, true /*fNeedNotificationPipe*/); 144 rc = VBoxServicePipeBufInit(&pData->stdIn, VBOXSERVICECTRLPIPEID_STDIN, 145 true /*fNeedNotificationPipe*/); 146 } 147 148 if (RT_SUCCESS(rc)) 149 { 150 pThread->enmType = kVBoxServiceCtrlThreadDataExec; 151 pThread->pvData = pData; 142 152 } 143 153 } 144 154 145 155 if (RT_FAILURE(rc)) 146 {147 156 VBoxServiceControlExecThreadDestroy(pData); 148 }149 else150 {151 pThread->enmType = kVBoxServiceCtrlThreadDataExec;152 pThread->pvData = pData;153 }154 157 return rc; 155 158 } … … 165 168 if (pData) 166 169 { 170 VBoxServiceVerbose(3, "ControlExec: [PID %u]: Destroying thread ...\n", 171 pData->uPID); 172 167 173 RTStrFree(pData->pszCmd); 168 174 if (pData->uNumEnvVars) … … 186 192 187 193 194 int VBoxServiceControlExecThreadAssignPID(PVBOXSERVICECTRLTHREADDATAEXEC pData, uint32_t uPID) 195 { 196 AssertPtrReturn(pData, VERR_INVALID_POINTER); 197 AssertReturn(uPID, VERR_INVALID_PARAMETER); 198 199 int rc = RTCritSectEnter(&g_GuestControlExecThreadsCritSect); 200 if (RT_SUCCESS(rc)) 201 { 202 /* Search an old thread using the desired PID and shut it down completely -- it's 203 * not used anymore. */ 204 const PVBOXSERVICECTRLTHREAD pOldThread = vboxServiceControlExecThreadGetByPID(uPID); 205 if ( pOldThread 206 && pOldThread->pvData != pData) 207 { 208 VBoxServiceVerbose(3, "ControlExec: PID %u was used before, shutting down stale exec thread ...\n", 209 uPID); 210 AssertPtr(pOldThread->pvData); 211 VBoxServiceControlExecThreadDestroy((PVBOXSERVICECTRLTHREADDATAEXEC)pOldThread->pvData); 212 } 213 /** @todo Remove node from thread list! */ 214 215 /* Assign PID to current thread. */ 216 pData->uPID = uPID; 217 VBoxServicePipeBufSetPID(&pData->stdIn, pData->uPID); 218 VBoxServicePipeBufSetPID(&pData->stdOut, pData->uPID); 219 VBoxServicePipeBufSetPID(&pData->stdErr, pData->uPID); 220 221 int rc2 = RTCritSectLeave(&g_GuestControlExecThreadsCritSect); 222 if (RT_SUCCESS(rc)) 223 rc = rc2; 224 } 225 226 return rc; 227 } 228 229 188 230 /** 189 231 * Finds a (formerly) started process given by its PID. … … 193 235 * @param uPID PID to search for. 194 236 */ 195 PVBOXSERVICECTRLTHREAD vboxServiceControlExecThreadGetByPID(uint32_t uPID)237 const PVBOXSERVICECTRLTHREAD vboxServiceControlExecThreadGetByPID(uint32_t uPID) 196 238 { 197 239 PVBOXSERVICECTRLTHREAD pNode = NULL; … … 236 278 if (VBoxServicePipeBufIsEnabled(&pData->stdIn)) 237 279 { 238 uint32_t cbWritten;239 280 /* 240 281 * Feed the data to the pipe. 241 282 */ 283 uint32_t cbWritten; 242 284 rc = VBoxServicePipeBufWriteToBuf(&pData->stdIn, pBuf, 243 285 cbSize, fPendingClose, &cbWritten); … … 279 321 if (RT_SUCCESS(rc)) 280 322 { 281 PVBOXSERVICECTRLTHREAD pNode = vboxServiceControlExecThreadGetByPID(uPID);323 const PVBOXSERVICECTRLTHREAD pNode = vboxServiceControlExecThreadGetByPID(uPID); 282 324 if (pNode) 283 325 { 284 PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)pNode->pvData;326 const PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)pNode->pvData; 285 327 AssertPtr(pData); 286 328 287 PVBOXSERVICECTRLEXECPIPEBUF pPipeBuf ;329 PVBOXSERVICECTRLEXECPIPEBUF pPipeBuf = NULL; 288 330 switch (uHandleId) 289 331 { … … 293 335 294 336 case OUTPUT_HANDLE_ID_STDOUT: /* StdOut */ 337 pPipeBuf = &pData->stdOut; 338 break; 339 295 340 default: 296 pPipeBuf = &pData->stdOut; 297 break; 298 } 299 AssertPtr(pPipeBuf); 300 341 AssertReleaseMsgFailed(("Unknown output handle ID (%u)\n", uHandleId)); 342 break; 343 } 344 if (!pPipeBuf) 345 return VERR_INVALID_PARAMETER; 346 347 #ifdef DEBUG_andy 348 VBoxServiceVerbose(4, "ControlExec: [PID %u]: Getting output from pipe buffer %u ...\n", 349 uPID, pPipeBuf->uPipeId); 350 #endif 301 351 /* If the stdout pipe buffer is enabled (that is, still could be filled by a running 302 352 * process) wait for the signal to arrive so that we don't return without any actual 303 353 * data read. */ 304 if (VBoxServicePipeBufIsEnabled(pPipeBuf)) 354 bool fEnabled = VBoxServicePipeBufIsEnabled(pPipeBuf); 355 if (fEnabled) 356 { 357 #ifdef DEBUG_andy 358 VBoxServiceVerbose(4, "ControlExec: [PID %u]: Waiting for pipe buffer %u\n", 359 uPID, pPipeBuf->uPipeId); 360 #endif 305 361 rc = VBoxServicePipeBufWaitForEvent(pPipeBuf, uTimeout); 306 362 } 307 363 if (RT_SUCCESS(rc)) 308 364 { … … 311 367 if (RT_SUCCESS(rc)) 312 368 { 369 if (fEnabled && !cbRead) 370 AssertMsgFailed(("Waited for pipe buffer %u, but nothing read!\n", 371 pPipeBuf->uPipeId)); 313 372 if (pcbRead) 314 373 *pcbRead = cbRead; 315 374 } 375 else 376 VBoxServiceError("ControlExec: [PID %u]: Unable to read from pipe buffer %u, rc=%Rrc\n", 377 uPID, pPipeBuf->uPipeId, rc); 316 378 } 317 379 } -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExecThread.h
r36548 r38113 27 27 const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars, 28 28 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS); 29 int VBoxServiceControlExecThreadAssignPID(PVBOXSERVICECTRLTHREADDATAEXEC pData, uint32_t uPID); 29 30 void VBoxServiceControlExecThreadDestroy(PVBOXSERVICECTRLTHREADDATAEXEC pData); 30 31 int VBoxServiceControlExecThreadSetInput(uint32_t uPID, bool fPendingClose, uint8_t *pBuf, -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r37375 r38113 102 102 # define VBOXSERVICE_FRIENDLY_NAME "VirtualBox Guest Additions Service" 103 103 /** The service description (only W2K+ atm) */ 104 # define VBOXSERVICE_DESCRIPTION "Manages VM runtime information, time synchronization, remote sysprepexecution and miscellaneous utilities for guest operating systems."104 # define VBOXSERVICE_DESCRIPTION "Manages VM runtime information, time synchronization, guest control execution and miscellaneous utilities for guest operating systems." 105 105 /** The following constant may be defined by including NtStatus.h. */ 106 106 # define STATUS_SUCCESS ((NTSTATUS)0x00000000L) … … 116 116 typedef enum VBOXSERVICECTRLPIPEID 117 117 { 118 VBOXSERVICECTRLPIPEID_STDIN_ERROR = 0, 118 VBOXSERVICECTRLPIPEID_STDIN = 0, 119 VBOXSERVICECTRLPIPEID_STDIN_ERROR, 119 120 VBOXSERVICECTRLPIPEID_STDIN_WRITABLE, 120 121 VBOXSERVICECTRLPIPEID_STDIN_INPUT_NOTIFY, … … 128 129 typedef struct 129 130 { 131 /** The PID the pipe is assigned to. */ 132 uint32_t uPID; 133 /** The pipe's Id of enum VBOXSERVICECTRLPIPEID. */ 134 uint8_t uPipeId; 130 135 /** The data buffer. */ 131 136 uint8_t *pbData; -
trunk/src/VBox/Additions/common/VBoxService/VBoxServicePipeBuf.cpp
r38085 r38113 28 28 #include "VBoxServicePipeBuf.h" 29 29 30 31 30 /** 32 31 * Initializes a pipe buffer. … … 34 33 * @returns IPRT status code. 35 34 * @param pBuf The pipe buffer to initialize. 35 * @param uId The pipe's ID handle. 36 36 * @param fNeedNotificationPipe Whether the buffer needs a notification 37 37 * pipe or not. 38 38 */ 39 int VBoxServicePipeBufInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fNeedNotificationPipe)39 int VBoxServicePipeBufInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, uint8_t uId, bool fNeedNotificationPipe) 40 40 { 41 41 AssertPtrReturn(pBuf, VERR_INVALID_POINTER); 42 42 43 43 /** @todo Add allocation size as function parameter! */ 44 pBuf->uPID = 0; /* We don't have the PID yet. */ 45 pBuf->uPipeId = uId; 44 46 pBuf->pbData = (uint8_t *)RTMemAlloc(_64K); /* Start with a 64k buffer. */ 45 47 AssertReturn(pBuf->pbData, VERR_NO_MEMORY); … … 59 61 rc = RTCritSectInit(&pBuf->CritSect); 60 62 if (RT_SUCCESS(rc) && fNeedNotificationPipe) 61 {62 63 rc = RTPipeCreate(&pBuf->hNotificationPipeR, &pBuf->hNotificationPipeW, 0); 63 if (RT_FAILURE(rc)) 64 { 65 RTCritSectDelete(&pBuf->CritSect); 66 if (pBuf->hEventSem != NIL_RTSEMEVENT) 67 RTSemEventDestroy(pBuf->hEventSem); 68 } 69 } 64 } 65 66 if (RT_FAILURE(rc)) 67 { 68 if (RTCritSectIsInitialized(&pBuf->CritSect)) 69 RTCritSectDelete(&pBuf->CritSect); 70 if (pBuf->hEventSem != NIL_RTSEMEVENT) 71 RTSemEventDestroy(pBuf->hEventSem); 70 72 } 71 73 return rc; … … 96 98 { 97 99 Assert(pBuf->cbSize >= pBuf->cbOffset); 98 if (*pcbToRead > pBuf->cbSize - pBuf->cbOffset) 99 *pcbToRead = pBuf->cbSize - pBuf->cbOffset; 100 101 if (*pcbToRead > cbBuffer) 102 *pcbToRead = cbBuffer; 103 104 if (*pcbToRead > 0) 105 { 106 memcpy(pbBuffer, pBuf->pbData + pBuf->cbOffset, *pcbToRead); 107 pBuf->cbOffset += *pcbToRead; 100 uint32_t cbToRead = *pcbToRead; 101 102 if (cbToRead > pBuf->cbSize - pBuf->cbOffset) 103 cbToRead = pBuf->cbSize - pBuf->cbOffset; 104 105 if (cbToRead > cbBuffer) 106 cbToRead = cbBuffer; 107 108 if (cbToRead) 109 { 110 memcpy(pbBuffer, &pBuf->pbData[pBuf->cbOffset], cbToRead); 111 pBuf->cbOffset += cbToRead; 108 112 109 113 if (pBuf->hEventSem != NIL_RTSEMEVENT) … … 114 118 115 119 #ifdef DEBUG_andy 116 VBoxServiceVerbose(4, "Pipe Buf[0x%p]: read=%u, size=%u, alloc=%u, off=%u\n",117 pBuf, *pcbToRead, pBuf->cbSize, pBuf->cbAllocated, pBuf->cbOffset);120 VBoxServiceVerbose(4, "Pipe [%u %u 0x%p %s] read pcbToRead=%u, cbSize=%u, cbAlloc=%u, cbOff=%u\n", 121 pBuf->uPID, pBuf->uPipeId, pBuf, pBuf->fEnabled ? "EN" : "DIS", cbToRead, pBuf->cbSize, pBuf->cbAllocated, pBuf->cbOffset); 118 122 #endif 123 *pcbToRead = cbToRead; 119 124 } 120 125 else 121 126 { 122 pbBuffer = NULL;123 127 *pcbToRead = 0; 124 128 } … … 132 136 133 137 138 /** 139 * Peeks for buffer data without moving the buffer's offset 140 * or touching any other internal data. 141 * 142 * @return IPRT status code. 143 * @param pBuf Pointer to pipe buffer to read the data from. 144 * @param pbBuffer Pointer to buffer to store the read out data. 145 * @param cbBuffer Size (in bytes) of the buffer where to store the data. 146 * @param cbOffset Offset (in bytes) where to start reading. 147 * @param pcbRead Pointer to desired amount (in bytes) of data to read, 148 * will reflect the actual amount read on return. 149 * @param pcbLeft Pointer to bytes left in buffer after the current read 150 * operation. 151 */ 134 152 int VBoxServicePipeBufPeek(PVBOXSERVICECTRLEXECPIPEBUF pBuf, 135 153 uint8_t *pbBuffer, uint32_t cbBuffer, … … 140 158 AssertPtrReturn(pbBuffer, VERR_INVALID_POINTER); 141 159 AssertReturn(cbBuffer, VERR_INVALID_PARAMETER); 142 143 int rc = RTCritSectEnter(&pBuf->CritSect); 144 i f (RT_SUCCESS(rc))145 {146 Assert(pBuf->cbSize >= pBuf->cbOffset);160 AssertReturn(pBuf->cbSize >= pBuf->cbOffset, VERR_BUFFER_OVERFLOW); 161 162 int rc = RTCritSectEnter(&pBuf->CritSect); 163 if (RT_SUCCESS(rc)) 164 { 147 165 if (cbOffset > pBuf->cbSize) 148 166 cbOffset = pBuf->cbSize; … … 152 170 if (cbToRead) 153 171 { 154 memcpy(pbBuffer, pBuf->pbData + cbOffset, cbToRead);172 memcpy(pbBuffer, &pBuf->pbData[cbOffset], cbToRead); 155 173 pbBuffer[cbBuffer - 1] = '\0'; 156 174 } … … 183 201 { 184 202 AssertPtrReturn(pBuf, VERR_INVALID_POINTER); 185 186 int rc = RTCritSectEnter(&pBuf->CritSect); 187 i f (RT_SUCCESS(rc))188 {189 AssertPtrReturn(pbData, VERR_INVALID_POINTER);203 AssertPtrReturn(pbData, VERR_INVALID_POINTER); 204 205 int rc = RTCritSectEnter(&pBuf->CritSect); 206 if (RT_SUCCESS(rc)) 207 { 190 208 if (pBuf->fEnabled) 191 209 { … … 269 287 *pcbWritten = cbData; 270 288 271 if (pBuf->hEventSem != NIL_RTSEMEVENT) 289 /* Only trigger signal if we really wrote something. */ 290 if ( cbData 291 && pBuf->hEventSem != NIL_RTSEMEVENT) 272 292 { 273 293 rc = RTSemEventSignal(pBuf->hEventSem); … … 276 296 277 297 #ifdef DEBUG_andy 278 VBoxServiceVerbose(4, "Pipe Buf[0x%p]: written=%u, size=%u, alloc=%u, off=%u\n",279 pBuf , cbData, pBuf->cbSize, pBuf->cbAllocated, pBuf->cbOffset);298 VBoxServiceVerbose(4, "Pipe [%u %u 0x%p %s] written cbData=%u, cbSize=%u, cbAlloc=%u, cbOff=%u\n", 299 pBuf->uPID, pBuf->uPipeId, pBuf, pBuf->fEnabled ? "EN" : "DIS", cbData, pBuf->cbSize, pBuf->cbAllocated, pBuf->cbOffset); 280 300 #endif 281 301 } … … 349 369 { 350 370 *pcbWritten = 0; 351 pBuf->fEnabled = false; 371 /* Don't set pBuf->fEnabled to false here! We just didn't write 372 * anything -- that doesn't mean this buffer is disabled (again). */ 352 373 } 353 374 } … … 377 398 378 399 bool fEnabled = false; 379 i f ( RTCritSectIsInitialized(&pBuf->CritSect)380 && RT_SUCCESS(RTCritSectEnter(&pBuf->CritSect)))400 int rc = RTCritSectEnter(&pBuf->CritSect); 401 if (RT_SUCCESS(rc)) 381 402 { 382 403 fEnabled = pBuf->fEnabled; … … 400 421 AssertPtrReturn(pBuf, false); 401 422 423 if (!RTCritSectIsInitialized(&pBuf->CritSect)) 424 return false; 425 402 426 bool fClosing = false; 403 if ( RTCritSectIsInitialized(&pBuf->CritSect) 404 && RT_SUCCESS(RTCritSectEnter(&pBuf->CritSect))) 427 if (RT_SUCCESS(RTCritSectEnter(&pBuf->CritSect))) 405 428 { 406 429 fClosing = pBuf->fPendingClose; … … 425 448 if (RT_SUCCESS(rc)) 426 449 { 450 bool fEnabledOld = pBuf->fEnabled; 427 451 pBuf->fEnabled = fEnabled; 428 /* Let waiter know that something has changed ... */ 429 if (pBuf->hEventSem) 452 if ( pBuf->fEnabled != fEnabledOld 453 && pBuf->hEventSem) 454 { 455 /* Let waiter know that something has changed ... */ 430 456 RTSemEventSignal(pBuf->hEventSem); 457 } 431 458 rc = RTCritSectLeave(&pBuf->CritSect); 432 459 } … … 435 462 436 463 464 /** 465 * Assigns a PID to the specified pipe buffer. Does not allow 466 * setting a new PID after a PID already was set. 467 * 468 * @return IPRT status code. 469 * @param pBuf The pipe buffer. 470 * @param uPID PID to assign. 471 */ 472 int VBoxServicePipeBufSetPID(PVBOXSERVICECTRLEXECPIPEBUF pBuf, uint32_t uPID) 473 { 474 AssertPtrReturn(pBuf, VERR_INVALID_POINTER); 475 476 int rc = RTCritSectEnter(&pBuf->CritSect); 477 if (RT_SUCCESS(rc)) 478 { 479 if (!pBuf->uPID) 480 pBuf->uPID = uPID; 481 rc = RTCritSectLeave(&pBuf->CritSect); 482 } 483 return rc; 484 } 485 486 487 /** 488 * Waits for the pipe buffer to get notified when something changed, like 489 * new data was written to or the buffer was disabled, i.e. not used anymore. 490 * 491 * @return IPRT status code. 492 * @param pBuf The pipe buffer. 493 * @param cMillies The maximum time (in ms) to wait for the event. 494 */ 437 495 int VBoxServicePipeBufWaitForEvent(PVBOXSERVICECTRLEXECPIPEBUF pBuf, RTMSINTERVAL cMillies) 438 496 { … … 455 513 void VBoxServicePipeBufDestroy(PVBOXSERVICECTRLEXECPIPEBUF pBuf) 456 514 { 457 AssertPtr(pBuf); 515 AssertPtrReturnVoid(pBuf); 516 458 517 if (pBuf->pbData) 459 518 { 460 RTMemFree(pBuf->pbData);461 pBuf-> pbData = NULL;519 pBuf->uPID = 0; 520 pBuf->uPipeId = 0; 462 521 pBuf->cbAllocated = 0; 463 522 pBuf->cbSize = 0; 464 523 pBuf->cbOffset = 0; 465 } 466 467 RTPipeClose(pBuf->hNotificationPipeR); 468 pBuf->hNotificationPipeR = NIL_RTPIPE; 469 RTPipeClose(pBuf->hNotificationPipeW); 470 pBuf->hNotificationPipeW = NIL_RTPIPE; 471 472 RTCritSectDelete(&pBuf->CritSect); 473 if (pBuf->hEventSem != NIL_RTSEMEVENT) 474 RTSemEventDestroy(pBuf->hEventSem); 475 } 476 524 525 RTPipeClose(pBuf->hNotificationPipeR); 526 pBuf->hNotificationPipeR = NIL_RTPIPE; 527 RTPipeClose(pBuf->hNotificationPipeW); 528 pBuf->hNotificationPipeW = NIL_RTPIPE; 529 530 if (RTCritSectIsInitialized(&pBuf->CritSect)) 531 RTCritSectDelete(&pBuf->CritSect); 532 if (pBuf->hEventSem != NIL_RTSEMEVENT) 533 RTSemEventDestroy(pBuf->hEventSem); 534 535 RTMemFree(pBuf->pbData); 536 pBuf->pbData = NULL; 537 } 538 } 539 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServicePipeBuf.h
r36744 r38113 21 21 #include "VBoxServiceInternal.h" 22 22 23 int VBoxServicePipeBufInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fNeedNotificationPipe);23 int VBoxServicePipeBufInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, uint8_t uId, bool fNeedNotificationPipe); 24 24 int VBoxServicePipeBufRead(PVBOXSERVICECTRLEXECPIPEBUF pBuf, 25 25 uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead); … … 34 34 bool VBoxServicePipeBufIsEnabled(PVBOXSERVICECTRLEXECPIPEBUF pBuf); 35 35 bool VBoxServicePipeBufIsClosing(PVBOXSERVICECTRLEXECPIPEBUF pBuf); 36 int VBoxServicePipeBufSetPID(PVBOXSERVICECTRLEXECPIPEBUF pBuf, uint32_t uPID); 36 37 int VBoxServicePipeBufSetStatus(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fEnabled); 37 38 int VBoxServicePipeBufWaitForEvent(PVBOXSERVICECTRLEXECPIPEBUF pBuf, RTMSINTERVAL cMillies);
Note:
See TracChangeset
for help on using the changeset viewer.