- Timestamp:
- Jun 5, 2022 8:15:44 PM (3 years ago)
- svn:sync-xref-src-repo-rev:
- 151707
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp
r95140 r95199 59 59 60 60 #if !defined(RT_OS_WINDOWS) 61 #include <signal.h> 62 static void HandleSignal(int sig); 61 # include <signal.h> 62 # include <unistd.h> 63 # include <sys/uio.h> 63 64 #endif 64 65 … … 396 397 397 398 #if !defined(RT_OS_WINDOWS) 398 static void 399 HandleSignal(int sig) 399 400 /** Signals we handle. */ 401 static int const g_aiSigs[] = { SIGHUP, SIGINT, SIGTERM, SIGUSR1 }; 402 403 /** The signal handler. */ 404 static void HandleSignal(int sig) 400 405 { 401 RT_NOREF(sig); 402 LogRel(("VBoxHeadless: received singal %d\n", sig)); 406 # if 1 407 struct iovec aSegs[8]; 408 int cSegs = 0; 409 aSegs[cSegs++].iov_base = (char *)"VBoxHeadless: signal "; 410 aSegs[cSegs++].iov_base = (char *)strsignal(sig); 411 const char *pszThread = RTThreadSelfName(); 412 if (pszThread) 413 { 414 aSegs[cSegs++].iov_base = (char *)" on thread "; 415 aSegs[cSegs++].iov_base = (char *)pszThread; 416 } 417 aSegs[cSegs++].iov_base = (char *)"\n"; 418 for (int i = 0; i < cSegs; i++) 419 aSegs[i].iov_len = strlen((const char *)aSegs[i].iov_base); 420 writev(2, aSegs, cSegs); 421 # else 422 LogRel(("VBoxHeadless: received signal %d\n", sig)); /** @todo r=bird: This is not at all safe. */ 423 # endif 403 424 g_fTerminateFE = true; 404 425 } 426 427 # ifdef RT_OS_DARWIN 428 429 /* For debugging. */ 430 uint32_t GetSignalMask(void) 431 { 432 /* For some totally messed up reason, the xnu sigprocmask actually returns 433 the signal mask of the calling thread rather than the process one 434 (p_sigmask), so can call sigprocmask just as well as pthread_sigmask here. */ 435 sigset_t Sigs; 436 RT_ZERO(Sigs); 437 sigprocmask(SIG_UNBLOCK, NULL, &Sigs); 438 RTMsgInfo("debug: thread %s mask: %.*Rhxs\n", RTThreadSelfName(), sizeof(Sigs), &Sigs); 439 for (int i = 0; i < 32; i++) 440 if (sigismember(&Sigs, i)) RTMsgInfo("debug: sig %2d blocked: %s\n", i, strsignal(i)); 441 return *(uint32_t const *)&Sigs; 442 } 443 444 /** 445 * Blocks or unblocks the signals we handle. 446 * 447 * @note Only for darwin does fProcess make a difference, all others always 448 * work on the calling thread regardless of the flag value. 449 */ 450 static void SetSignalMask(bool fBlock, bool fProcess) 451 { 452 sigset_t Sigs; 453 sigemptyset(&Sigs); 454 for (unsigned i = 0; i < RT_ELEMENTS(g_aiSigs); i++) 455 sigaddset(&Sigs, g_aiSigs[i]); 456 if (fProcess) 457 { 458 if (sigprocmask(fBlock ? SIG_BLOCK : SIG_UNBLOCK, &Sigs, NULL) != 0) 459 RTMsgError("sigprocmask failed: %d", errno); 460 } 461 else 462 { 463 if (pthread_sigmask(fBlock ? SIG_BLOCK : SIG_UNBLOCK, &Sigs, NULL) != 0) 464 RTMsgError("pthread_sigmask failed: %d", errno); 465 } 466 } 467 468 /** 469 * @callback_method_impl{FNRTTHREAD, Signal wait thread} 470 */ 471 static DECLCALLBACK(int) SigThreadProc(RTTHREAD hThreadSelf, void *pvUser) 472 { 473 RT_NOREF(hThreadSelf, pvUser); 474 475 /* The signals to wait for: */ 476 sigset_t SigSetWait; 477 sigemptyset(&SigSetWait); 478 for (unsigned i = 0; i < RT_ELEMENTS(g_aiSigs); i++) 479 sigaddset(&SigSetWait, g_aiSigs[i]); 480 481 /* The wait + processing loop: */ 482 for (;;) 483 { 484 int iSignal = -1; 485 if (sigwait(&SigSetWait, &iSignal) == 0) 486 { 487 g_fTerminateFE = true; 488 RTMsgInfo("Caught signal: %s\n", strsignal(iSignal)); 489 LogRel(("VBoxHeadless: Caught signal: %s\n", strsignal(iSignal))); 490 } 491 492 /** @todo this is a little bit racy... */ 493 if (g_fTerminateFE && gEventQ != NULL) 494 gEventQ->interruptEventQueueProcessing(); 495 } 496 } 497 498 /** The handle to the signal wait thread. */ 499 static RTTHREAD g_hSigThread = NIL_RTTHREAD; 500 501 # endif /* RT_OS_DARWIN */ 502 503 static void SetUpSignalHandlers(void) 504 { 505 signal(SIGPIPE, SIG_IGN); 506 signal(SIGTTOU, SIG_IGN); 507 508 /* Don't touch SIGUSR2 as IPRT could be using it for RTThreadPoke(). */ 509 for (unsigned i = 0; i < RT_ELEMENTS(g_aiSigs); i++) 510 { 511 struct sigaction sa; 512 RT_ZERO(sa); 513 sa.sa_handler = HandleSignal; 514 if (sigaction(g_aiSigs[i], &sa, NULL) != 0) 515 RTMsgError("sigaction failed for signal #%u: %d", g_aiSigs[i], errno); 516 } 517 518 # if defined(RT_OS_DARWIN) 519 /* 520 * On darwin processEventQueue() does not return with VERR_INTERRUPTED or 521 * similar if a signal arrives while we're waiting for events. So, in 522 * order to respond promptly to signals after they arrives, we use a 523 * dedicated thread for fielding the signals and poking the event queue 524 * after each signal. 525 * 526 * We block the signals for all threads (this is fine as the p_sigmask 527 * isn't actually used for anything at all and wont prevent signal 528 * delivery). The signal thread should have them blocked as well, as it 529 * uses sigwait to do the waiting (better than sigsuspend, as we can safely 530 * LogRel the signal this way). 531 */ 532 if (g_hSigThread == NIL_RTTHREAD) 533 { 534 SetSignalMask(true /*fBlock */, true /*fProcess*/); 535 int vrc = RTThreadCreate(&g_hSigThread, SigThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, 0, "SigWait"); 536 if (RT_FAILURE(vrc)) 537 { 538 RTMsgError("Failed to create signal waiter thread: %Rrc", vrc); 539 SetSignalMask(false /*fBlock */, false /*fProcess*/); 540 } 541 } 542 # endif 543 } 544 405 545 #endif /* !RT_OS_WINDOWS */ 406 546 … … 1302 1442 */ 1303 1443 #if !defined(RT_OS_WINDOWS) 1304 signal(SIGPIPE, SIG_IGN); 1305 signal(SIGTTOU, SIG_IGN); 1306 1307 struct sigaction sa; 1308 RT_ZERO(sa); 1309 sa.sa_handler = HandleSignal; 1310 sigaction(SIGHUP, &sa, NULL); 1311 sigaction(SIGINT, &sa, NULL); 1312 sigaction(SIGTERM, &sa, NULL); 1313 sigaction(SIGUSR1, &sa, NULL); 1314 /* Don't touch SIGUSR2 as IPRT could be using it for RTThreadPoke(). */ 1315 1316 #else /* RT_OS_WINDOWS */ 1444 ::SetUpSignalHandlers(); 1445 #else 1317 1446 /* 1318 1447 * Register windows console signal handler to react to Ctrl-C, … … 1365 1494 for (;;) 1366 1495 { 1496 if (g_fTerminateFE) 1497 { 1498 LogRel(("VBoxHeadless: processEventQueue: %Rrc, termination requested\n", vrc)); 1499 break; 1500 } 1501 1367 1502 vrc = gEventQ->processEventQueue(RT_INDEFINITE_WAIT); 1368 1503
Note:
See TracChangeset
for help on using the changeset viewer.