Changeset 29817 in vbox for trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
- Timestamp:
- May 26, 2010 1:54:41 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
r29776 r29817 57 57 #ifdef RT_OS_WINDOWS 58 58 /** Signal shutdown to the Windows service thread. */ 59 bool volatile g_WindowsServiceShutdown;59 static bool volatile g_fWindowsServiceShutdown; 60 60 /** Event the Windows service thread waits for shutdown. */ 61 RTSEMEVENT g_WindowsServiceEvent;61 static RTSEMEVENT g_hEvtWindowsService; 62 62 #endif 63 63 … … 155 155 * Displays a syntax error message. 156 156 * 157 * @returns 1157 * @returns RTEXITCODE_SYNTAX. 158 158 * @param pszFormat The message text. 159 159 * @param ... Format arguments. 160 160 */ 161 intVBoxServiceSyntax(const char *pszFormat, ...)161 RTEXITCODE VBoxServiceSyntax(const char *pszFormat, ...) 162 162 { 163 163 RTStrmPrintf(g_pStdErr, "%s: syntax error: ", g_pszProgName); … … 168 168 va_end(va); 169 169 170 return 1;170 return RTEXITCODE_SYNTAX; 171 171 } 172 172 … … 175 175 * Displays an error message. 176 176 * 177 * @returns 1177 * @returns RTEXITCODE_FAILURE. 178 178 * @param pszFormat The message text. 179 179 * @param ... Format arguments. 180 180 */ 181 intVBoxServiceError(const char *pszFormat, ...)181 RTEXITCODE VBoxServiceError(const char *pszFormat, ...) 182 182 { 183 183 RTStrmPrintf(g_pStdErr, "%s: error: ", g_pszProgName); … … 192 192 va_end(va); 193 193 194 return 1;194 return RTEXITCODE_FAILURE; 195 195 } 196 196 … … 308 308 VBoxServiceVerbose(2, "Initializing services ...\n"); 309 309 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 310 {311 310 if (g_aServices[j].fEnabled) 312 311 { … … 326 325 } 327 326 } 328 }329 327 330 328 /* … … 357 355 } 358 356 359 #ifdef RT_OS_WINDOWS360 if (RT_SUCCESS(rc))361 {362 /* Block the main thread. */363 VBoxServiceVerbose(1, "Waiting in main thread\n");364 int rc = RTSemEventCreate(&g_WindowsServiceEvent);365 AssertRC(rc);366 for (;;)367 {368 if (g_WindowsServiceShutdown)369 break;370 rc = RTSemEventWait(g_WindowsServiceEvent, RT_INDEFINITE_WAIT);371 AssertRC(rc);372 }373 RTSemEventDestroy(g_WindowsServiceEvent);374 g_WindowsServiceEvent = NIL_RTSEMEVENT;375 }376 #endif377 357 return rc; 378 358 } … … 389 369 int rc = VINF_SUCCESS; 390 370 391 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 392 ASMAtomicXchgBool(&g_aServices[j].fShutdown, true); 371 /* 372 * Signal all the services. 373 */ 374 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 375 ASMAtomicWriteBool(&g_aServices[j].fShutdown, true); 376 377 /* 378 * Do the pfnStop callback on all running services. 379 */ 393 380 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 394 381 if (g_aServices[j].fStarted) … … 397 384 g_aServices[j].pDesc->pfnStop(); 398 385 } 386 387 /* 388 * Wait for all the service threads to complete. 389 */ 399 390 for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++) 400 391 { … … 411 402 #ifdef RT_OS_WINDOWS 412 403 /* Notify SCM that it takes a bit longer ... */ 413 VBoxServiceWinSetSt atus(SERVICE_STOP_PENDING, i);404 VBoxServiceWinSetStopPendingStatus(i + j*32); 414 405 #endif 415 406 } … … 423 414 #ifdef RT_OS_WINDOWS 424 415 /* 425 * As we're now done terminating all service threads, 426 * we have to stop the main thread as well (if defined). Note that the termination 427 * function will be called in a later context (when the main thread returns from the worker 428 * function). 429 */ 430 if (g_WindowsServiceEvent != NIL_RTSEMEVENT) 416 * Wake up and tell the main() thread that we're shutting down (it's 417 * sleeping in VBoxServiceMainWait). 418 */ 419 if (g_hEvtWindowsService != NIL_RTSEMEVENT) 431 420 { 432 421 VBoxServiceVerbose(3, "Stopping the main thread...\n"); 433 ASMAtomic XchgBool(&g_WindowsServiceShutdown, true);434 rc = RTSemEventSignal(g_ WindowsServiceEvent);422 ASMAtomicWriteBool(&g_fWindowsServiceShutdown, true); 423 rc = RTSemEventSignal(g_hEvtWindowsService); 435 424 AssertRC(rc); 436 425 } … … 442 431 443 432 444 #ifndef RT_OS_WINDOWS 445 /** 446 * Block all important signals, then explicitly wait until one of these 447 * signal arrives. 448 */ 449 static void VBoxServiceWaitSignal(void) 450 { 433 /** 434 * Block the main thread until the service shuts down. 435 */ 436 void VBoxServiceMainWait(void) 437 { 438 int rc; 439 440 #ifdef RT_OS_WINDOWS 441 /* 442 * Wait for the semaphore to be signalled. 443 */ 444 VBoxServiceVerbose(1, "Waiting in main thread\n"); 445 rc = RTSemEventCreate(&g_hEvtWindowsService); 446 AssertRC(rc); 447 while (!ASMAtomicReadBool(&g_fWindowsServiceShutdown)) 448 { 449 rc = RTSemEventWait(g_hEvtWindowsService, RT_INDEFINITE_WAIT); 450 AssertRC(rc); 451 } 452 RTSemEventDestroy(g_hEvtWindowsService); 453 g_hEvtWindowsService = NIL_RTSEMEVENT; 454 455 #else 456 /* 457 * Wait explicitly for a HUP, INT, QUIT, ABRT or TERM signal, blocking 458 * all important signals. 459 * 460 * The annoying EINTR/ERESTART loop is for the benefit of Solaris where 461 * sigwait returns when we receive a SIGCHLD. Kind of makes sense since 462 */ 451 463 sigset_t signalMask; 452 int iSignal;453 464 sigemptyset(&signalMask); 454 465 sigaddset(&signalMask, SIGHUP); … … 459 470 pthread_sigmask(SIG_BLOCK, &signalMask, NULL); 460 471 461 /* This loop is required on Solaris at least. FreeBSD doesn't know ERESTART. */ 462 int rc; 472 int iSignal; 463 473 do 464 474 { … … 472 482 ); 473 483 474 VBoxServiceVerbose(3, "VBoxServiceWaitSignal: Received signal %d (rc=%d)\n", iSignal, rc); 475 } 484 VBoxServiceVerbose(3, "VBoxServiceMainWait: Received signal %d (rc=%d)\n", iSignal, rc); 476 485 #endif /* !RT_OS_WINDOWS */ 486 } 477 487 478 488 … … 653 663 * Daemonize if requested. 654 664 */ 665 RTEXITCODE rcExit; 655 666 if (fDaemonize && !fDaemonized) 656 667 { 657 668 #ifdef RT_OS_WINDOWS 658 /** @todo Should do something like VBoxSVC here, OR automatically re-register659 * the service and start it. Involving VbglR3Daemonize isn't an option660 * here.661 *662 * Also, the idea here, IIRC, was to map the sub service to windows663 * services. The todo below is for mimicking windows services on664 * non-windows systems. Not sure if this is doable or not, but in anycase665 * this code can be moved into -win.666 *667 * You should return when StartServiceCtrlDispatcher, btw., not668 * continue.669 */670 669 VBoxServiceVerbose(2, "Starting service dispatcher ...\n"); 671 if (!StartServiceCtrlDispatcher(&g_aServiceTable[0])) 672 return VBoxServiceError("StartServiceCtrlDispatcher: %u. Please start %s with option -f (foreground)!", 673 GetLastError(), g_pszProgName); 674 /* Service now lives in the control dispatcher registered above. */ 670 rcExit = VBoxServiceWinEnterCtrlDispatcher(); 675 671 #else 676 672 VBoxServiceVerbose(1, "Daemonizing...\n"); … … 694 690 */ 695 691 rc = VBoxServiceStartServices(); 696 #ifndef RT_OS_WINDOWS 692 rcExit = RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; 697 693 if (RT_SUCCESS(rc)) 698 VBoxServiceWaitSignal(); 699 #endif 694 VBoxServiceMainWait(); 700 695 VBoxServiceStopServices(); 701 696 } … … 713 708 714 709 VBoxServiceVerbose(0, "Ended.\n"); 715 return RT_SUCCESS(rc) ? 0 : 1; 716 } 710 return rcExit; 711 } 712
Note:
See TracChangeset
for help on using the changeset viewer.