Changeset 36331 in vbox
- Timestamp:
- Mar 21, 2011 7:17:12 PM (14 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxService
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxService-win.cpp
r35715 r36331 345 345 } 346 346 else 347 { 347 348 vboxServiceWinSetStatus(SERVICE_STOPPED, 0); 349 #if 0 /** @todo r=bird: Enable this if SERVICE_CONTROL_STOP isn't triggered automatically */ 350 VBoxServiceStopServices(); 351 #endif 352 } 348 353 } 349 354 /**@todo r=bird: else vboxServiceWinSetStatus(SERVICE_STOPPED, 0); ? */ -
trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
r36330 r36331 40 40 #include <iprt/buildconfig.h> 41 41 #include <iprt/initterm.h> 42 #include <iprt/message.h> 42 43 #include <iprt/path.h> 43 44 #include <iprt/semaphore.h> … … 77 78 /** The worker thread. NIL_RTTHREAD if it's the main thread. */ 78 79 RTTHREAD Thread; 80 /** Whether Pre-init was called. */ 81 bool fPreInited; 79 82 /** Shutdown indicator. */ 80 83 bool volatile fShutdown; … … 88 91 { 89 92 #ifdef VBOXSERVICE_CONTROL 90 { &g_Control, NIL_RTTHREAD, false, false, false, true },93 { &g_Control, NIL_RTTHREAD, false, false, false, false, true }, 91 94 #endif 92 95 #ifdef VBOXSERVICE_TIMESYNC 93 { &g_TimeSync, NIL_RTTHREAD, false, false, false, true },96 { &g_TimeSync, NIL_RTTHREAD, false, false, false, false, true }, 94 97 #endif 95 98 #ifdef VBOXSERVICE_CLIPBOARD 96 { &g_Clipboard, NIL_RTTHREAD, false, false, false, true },99 { &g_Clipboard, NIL_RTTHREAD, false, false, false, false, true }, 97 100 #endif 98 101 #ifdef VBOXSERVICE_VMINFO 99 { &g_VMInfo, NIL_RTTHREAD, false, false, false, true },102 { &g_VMInfo, NIL_RTTHREAD, false, false, false, false, true }, 100 103 #endif 101 104 #ifdef VBOXSERVICE_CPUHOTPLUG 102 { &g_CpuHotPlug, NIL_RTTHREAD, false, false, false, true },105 { &g_CpuHotPlug, NIL_RTTHREAD, false, false, false, false, true }, 103 106 #endif 104 107 #ifdef VBOXSERVICE_MANAGEMENT 105 108 # ifdef VBOX_WITH_MEMBALLOON 106 { &g_MemBalloon, NIL_RTTHREAD, false, false, false, true },109 { &g_MemBalloon, NIL_RTTHREAD, false, false, false, false, true }, 107 110 # endif 108 { &g_VMStatistics, NIL_RTTHREAD, false, false, false, true },111 { &g_VMStatistics, NIL_RTTHREAD, false, false, false, false, true }, 109 112 #endif 110 113 #if defined(VBOX_WITH_PAGE_SHARING) && defined(RT_OS_WINDOWS) 111 { &g_PageSharing, NIL_RTTHREAD, false, false, false, true },114 { &g_PageSharing, NIL_RTTHREAD, false, false, false, false, true }, 112 115 #endif 113 116 #ifdef VBOX_WITH_SHARED_FOLDERS 114 { &g_AutoMount, NIL_RTTHREAD, false, false, false, true },117 { &g_AutoMount, NIL_RTTHREAD, false, false, false, false, true }, 115 118 #endif 116 119 }; … … 232 235 * Reports the current VBoxService status to the host. 233 236 * 237 * This makes sure that the Failed state is sticky. 238 * 234 239 * @return IPRT status code. 235 240 * @param enmStatus Status to report to the host. … … 237 242 int VBoxServiceReportStatus(VBoxGuestFacilityStatus enmStatus) 238 243 { 239 /* Report the host that we're up and running! */ 240 int rc = VbglR3ReportAdditionsStatus(VBoxGuestFacilityType_VBoxService, 241 enmStatus, 0 /* Flags */); 242 if (RT_FAILURE(rc)) 243 VBoxServiceError("Could not report VBoxService status (%u), rc=%Rrc\n", enmStatus, rc); 244 return rc; 244 /* 245 * VBoxGuestFacilityStatus_Failed is sticky. 246 */ 247 static VBoxGuestFacilityStatus s_enmLastStatus = VBoxGuestFacilityStatus_Inactive; 248 if (s_enmLastStatus != VBoxGuestFacilityStatus_Failed) 249 { 250 int rc = VbglR3ReportAdditionsStatus(VBoxGuestFacilityType_VBoxService, 251 enmStatus, 0 /* Flags */); 252 if (RT_FAILURE(rc)) 253 { 254 VBoxServiceError("Could not report VBoxService status (%u), rc=%Rrc\n", enmStatus, rc); 255 return rc; 256 } 257 s_enmLastStatus = enmStatus; 258 } 259 return VINF_SUCCESS; 245 260 } 246 261 … … 304 319 RTThreadUserSignal(ThreadSelf); 305 320 return rc; 321 } 322 323 324 /** 325 * Lazily calls the pfnPreInit method on each service. 326 * 327 * @returns VBox status code, error message displayed. 328 */ 329 static RTEXITCODE vboxServiceLazyPreInit(void) 330 { 331 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 332 if (!g_aServices[j].fPreInited) 333 { 334 int rc = g_aServices[j].pDesc->pfnPreInit(); 335 if (RT_FAILURE(rc)) 336 return VBoxServiceError("Service '%s' failed pre-init: %Rrc\n", g_aServices[j].pDesc->pszName, rc); 337 g_aServices[j].fPreInited = true; 338 } 339 return RTEXITCODE_SUCCESS; 306 340 } 307 341 … … 344 378 VBoxServiceError("Service '%s' failed to initialize: %Rrc\n", 345 379 g_aServices[j].pDesc->pszName, rc); 380 VBoxServiceReportStatus(VBoxGuestFacilityStatus_Failed); 346 381 return rc; 347 382 } … … 373 408 g_aServices[j].fStarted = true; 374 409 375 /* Wait for the thread to initialize. 376 * 377 * @todo There is a race between waiting and checking 378 * the fShutdown flag of a thread here and processing 379 * the thread's actual worker loop. If the thread decides 380 * to exit the loop before we skipped the fShutdown check 381 * below the service will fail to start! */ 410 /* Wait for the thread to initialize. */ 411 /** @todo There is a race between waiting and checking 412 * the fShutdown flag of a thread here and processing 413 * the thread's actual worker loop. If the thread decides 414 * to exit the loop before we skipped the fShutdown check 415 * below the service will fail to start! */ 382 416 RTThreadUserWait(g_aServices[j].Thread, 60 * 1000); 383 417 if (g_aServices[j].fShutdown) … … 407 441 int VBoxServiceStopServices(void) 408 442 { 409 int rc = VINF_SUCCESS;410 411 443 VBoxServiceReportStatus(VBoxGuestFacilityStatus_Terminating); 412 444 … … 430 462 * Wait for all the service threads to complete. 431 463 */ 464 int rc = VINF_SUCCESS; 432 465 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 433 466 { … … 437 470 { 438 471 VBoxServiceVerbose(2, "Waiting for service '%s' to stop ...\n", g_aServices[j].pDesc->pszName); 472 int rc2 = VINF_SUCCESS; 439 473 for (int i = 0; i < 30; i++) /* Wait 30 seconds in total */ 440 474 { 441 rc = RTThreadWait(g_aServices[j].Thread, 1000 /* Wait 1 second */, NULL);442 if (RT_SUCCESS(rc ))475 rc2 = RTThreadWait(g_aServices[j].Thread, 1000 /* Wait 1 second */, NULL); 476 if (RT_SUCCESS(rc2)) 443 477 break; 444 478 #ifdef RT_OS_WINDOWS … … 447 481 #endif 448 482 } 449 if (RT_FAILURE(rc)) 450 VBoxServiceError("Service '%s' failed to stop. (%Rrc)\n", g_aServices[j].pDesc->pszName, rc); 483 if (RT_FAILURE(rc2)) 484 { 485 VBoxServiceError("Service '%s' failed to stop. (%Rrc)\n", g_aServices[j].pDesc->pszName, rc2); 486 rc = rc2; 487 } 451 488 } 452 489 VBoxServiceVerbose(3, "Terminating service '%s' (%d) ...\n", g_aServices[j].pDesc->pszName, j); … … 459 496 * sleeping in VBoxServiceMainWait). 460 497 */ 498 ASMAtomicWriteBool(&g_fWindowsServiceShutdown, true); 461 499 if (g_hEvtWindowsService != NIL_RTSEMEVENT) 462 500 { 463 501 VBoxServiceVerbose(3, "Stopping the main thread...\n"); 464 ASMAtomicWriteBool(&g_fWindowsServiceShutdown, true); 465 rc = RTSemEventSignal(g_hEvtWindowsService); 466 AssertRC(rc); 467 } 468 #endif 469 470 VBoxServiceVerbose(2, "Stopping services returned: rc=%Rrc\n", rc); 471 VBoxServiceReportStatus(RT_SUCCESS(rc) 472 ? VBoxGuestFacilityStatus_Paused : VBoxGuestFacilityStatus_Failed); 502 int rc2 = RTSemEventSignal(g_hEvtWindowsService); 503 AssertRC(rc2); 504 } 505 #endif 506 507 VBoxServiceVerbose(2, "Stopping services returning: %Rrc\n", rc); 508 VBoxServiceReportStatus(RT_SUCCESS(rc) ? VBoxGuestFacilityStatus_Paused : VBoxGuestFacilityStatus_Failed); 473 509 return rc; 474 510 } … … 535 571 int main(int argc, char **argv) 536 572 { 573 RTEXITCODE rcExit; 574 537 575 /* 538 576 * Init globals and such. 539 577 */ 540 RTR3Init(); 541 578 int rc = RTR3Init(); 579 if (RT_FAILURE(rc)) 580 return RTMsgInitFailure(rc); 542 581 g_pszProgName = RTPathFilename(argv[0]); 543 582 544 int rc;545 583 #ifdef VBOXSERVICE_TOOLBOX 584 /* 585 * Run toolbox code before all other stuff since these things are simpler 586 * shell/file/text utility like programs that just happens to be inside 587 * VBoxService and shouldn't be subject to /dev/vboxguest, pid-files and 588 * global mutex restrictions. 589 */ 590 # if 0 /** @todo r=bird: pending argv[0] bugfixing. */ 591 if (VBoxServiceToolboxMain(argc, argv, &rcExit)) 592 return rcExit; 593 # else 546 594 if (argc > 1) 547 { 548 /* 549 * Run toolbox code before all other stuff, especially before checking the global 550 * mutex because VBoxService might spawn itself to execute some commands. 551 */ 552 int iExitCode; 553 if (VBoxServiceToolboxMain(argc - 1, &argv[1], &iExitCode)) 554 return iExitCode; 555 } 595 if (VBoxServiceToolboxMain(argc - 1, &argv[1], &rcExit)) 596 return rcExit; 597 # endif 556 598 #endif 557 599 … … 567 609 { 568 610 if (rc == VERR_ACCESS_DENIED) 569 return VBoxServiceError(" Not enough rights to start %s! Please start with Administrator/root privileges!\n",611 return VBoxServiceError("Insufficient privileges to start %s! Please start with Administrator/root privileges!\n", 570 612 g_pszProgName); 571 else 572 return VBoxServiceError("VbglR3Init failed with rc=%Rrc.\n", rc); 613 return VBoxServiceError("VbglR3Init failed with rc=%Rrc.\n", rc); 573 614 } 574 615 … … 584 625 585 626 /* 586 * Parse the arguments 587 * .627 * Parse the arguments. 628 * 588 629 * Note! This code predates RTGetOpt, thus the manual parsing. 589 630 */ … … 640 681 641 682 if (!fFound) 683 { 684 rcExit = vboxServiceLazyPreInit(); 685 if (rcExit != RTEXITCODE_SUCCESS) 686 return rcExit; 687 642 688 for (unsigned j = 0; !fFound && j < RT_ELEMENTS(g_aServices); j++) 643 689 { … … 649 695 return rc; 650 696 } 697 } 651 698 if (!fFound) 652 699 return VBoxServiceSyntax("Unknown option '%s'\n", argv[i]); … … 695 742 default: 696 743 { 744 rcExit = vboxServiceLazyPreInit(); 745 if (rcExit != RTEXITCODE_SUCCESS) 746 return rcExit; 747 697 748 bool fFound = false; 698 749 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 699 750 { 700 rc = g_aServices[j].pDesc->pfnPreInit(); 701 if (RT_FAILURE(rc)) 702 return VBoxServiceError("Service '%s' failed pre-init: %Rrc\n", g_aServices[j].pDesc->pszName, rc); 703 else 704 rc = g_aServices[j].pDesc->pfnOption(&psz, argc, argv, &i); 751 rc = g_aServices[j].pDesc->pfnOption(&psz, argc, argv, &i); 705 752 fFound = rc == VINF_SUCCESS; 706 753 if (fFound) … … 721 768 return VBoxServiceSyntax("At least one service must be enabled.\n"); 722 769 770 /* Call pre-init if we didn't do it already. */ 771 rcExit = vboxServiceLazyPreInit(); 772 if (rcExit != RTEXITCODE_SUCCESS) 773 return rcExit; 774 723 775 #ifdef RT_OS_WINDOWS 724 776 /* … … 764 816 * Daemonize if requested. 765 817 */ 766 RTEXITCODE rcExit;767 818 if (fDaemonize && !fDaemonized) 768 819 { … … 782 833 #endif 783 834 { 784 VBoxServiceReportStatus(VBoxGuestFacilityStatus_PreInit);785 786 835 /* 787 836 * Windows: We're running the service as a console application now. Start the … … 797 846 VBoxServiceMainWait(); 798 847 VBoxServiceStopServices(); 799 800 /* Only report the "terminated" status when we really did run the internal services -- 801 * otherwise we also wrongly would report "terminated" when a user simply 802 * wants to query the version or the command line help. */ 803 VBoxServiceReportStatus(VBoxGuestFacilityStatus_Terminated); 804 } 848 } 849 VBoxServiceReportStatus(VBoxGuestFacilityStatus_Terminated); 805 850 806 851 #ifdef RT_OS_WINDOWS -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r36330 r36331 286 286 287 287 #ifdef VBOXSERVICE_TOOLBOX 288 extern bool VBoxServiceToolboxMain(int argc, char **argv, int *piExitCode);288 extern bool VBoxServiceToolboxMain(int argc, char **argv, RTEXITCODE *prcExit); 289 289 #endif 290 290 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp
r36305 r36331 210 210 * @param argv Pointer to argument array. 211 211 */ 212 static intVBoxServiceToolboxMkDir(int argc, char **argv)212 static RTEXITCODE VBoxServiceToolboxMkDir(int argc, char **argv) 213 213 { 214 214 static const RTGETOPTDEF s_aOptions[] = … … 332 332 * @param argv Pointer to argument array. 333 333 */ 334 static intVBoxServiceToolboxCat(int argc, char **argv)334 static RTEXITCODE VBoxServiceToolboxCat(int argc, char **argv) 335 335 { 336 336 static const RTGETOPTDEF s_aOptions[] = … … 486 486 * @param argc Number of arguments. 487 487 * @param argv Pointer to argument array. 488 * @param p iExitCode Pointer to receive exit code when internal command489 * was handled.490 */ 491 bool VBoxServiceToolboxMain(int argc, char **argv, int *piExitCode)488 * @param prcExit Where to store the exit code when an 489 * internal toolbox command was handled. 490 */ 491 bool VBoxServiceToolboxMain(int argc, char **argv, RTEXITCODE *prcExit) 492 492 { 493 493 if (argc > 0) /* Do we have at least a main command? */ … … 496 496 || !strcmp(argv[0], "vbox_cat")) 497 497 { 498 *p iExitCode= VBoxServiceToolboxCat(argc, argv);498 *prcExit = VBoxServiceToolboxCat(argc, argv); 499 499 return true; 500 500 } 501 else if ( !strcmp(argv[0], "mkdir") 502 || !strcmp(argv[0], "vbox_mkdir")) 501 502 if ( !strcmp(argv[0], "mkdir") 503 || !strcmp(argv[0], "vbox_mkdir")) 503 504 { 504 *p iExitCode= VBoxServiceToolboxMkDir(argc, argv);505 *prcExit = VBoxServiceToolboxMkDir(argc, argv); 505 506 return true; 506 507 }
Note:
See TracChangeset
for help on using the changeset viewer.