Changeset 103300 in vbox for trunk/src/libs
- Timestamp:
- Feb 11, 2024 8:33:57 PM (13 months ago)
- svn:sync-xref-src-repo-rev:
- 161594
- Location:
- trunk/src/libs/xpcom18a4
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/libs/xpcom18a4/Makefile.kmk
r102470 r103300 106 106 VBoxXPCOM \ 107 107 VBoxXPCOMIPCC 108 ifdef VBOX_WITH_XPCOMIPCD_IN_VBOX_SVC 109 VBOX_XPCOM_DLLS += \ 110 VBoxXPCOMIPCD 111 endif 112 108 113 DLLS += $(VBOX_XPCOM_DLLS) 109 114 … … 134 139 tstPrimitiveTest 135 140 endif # VBOX_WITH_TESTCASES 136 PROGRAMS += VBoxXPCOMIPCD 141 ifndef VBOX_WITH_XPCOMIPCD_IN_VBOX_SVC 142 PROGRAMS += VBoxXPCOMIPCD 143 endif 137 144 138 145 endif # !VBOX_ONLY_SDK && (!defined(VBOX_ONLY_EXTPACKS) || !defined(VBOX_ONLY_EXTPACKS_USE_IMPLIBS)) … … 754 761 TEMPLATE_XPComIpcDll = XPCOM IPC libraries 755 762 TEMPLATE_XPComIpcDll_EXTENDS = XPComDll 756 TEMPLATE_XPComIpcDll_DEFS = $(TEMPLATE_XPComDll_DEFS) BUILD_DCONNECT=1 757 ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING 758 TEMPLATE_XPComIpcDll_DEFS += IPC_DAEMON_APP_NAME="VBoxXPCOMIPCD$(SUFF_EXE)" 763 TEMPLATE_XPComIpcDll_DEFS = \ 764 $(TEMPLATE_XPComDll_DEFS) \ 765 BUILD_DCONNECT=1 \ 766 $(if $(VBOX_WITH_XPCOMIPCD_IN_VBOX_SVC),VBOX_WITH_XPCOMIPCD_IN_VBOX_SVC,) 767 768 ifdef VBOX_WITH_XPCOMIPCD_IN_VBOX_SVC 769 ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING 770 TEMPLATE_XPComIpcDll_DEFS += IPC_DAEMON_APP_NAME="VBoxSVC$(SUFF_EXE)" 771 else 772 TEMPLATE_XPComIpcDll_DEFS += IPC_DAEMON_APP_NAME=\"VBoxSVC$(SUFF_EXE)\" 773 endif 759 774 else 760 TEMPLATE_XPComIpcDll_DEFS += IPC_DAEMON_APP_NAME=\"VBoxXPCOMIPCD$(SUFF_EXE)\" 775 ifdef VBOX_WITH_AUTOMATIC_DEFS_QUOTING 776 TEMPLATE_XPComIpcDll_DEFS += IPC_DAEMON_APP_NAME="VBoxXPCOMIPCD$(SUFF_EXE)" 777 else 778 TEMPLATE_XPComIpcDll_DEFS += IPC_DAEMON_APP_NAME=\"VBoxXPCOMIPCD$(SUFF_EXE)\" 779 endif 761 780 endif 762 781 ifdef IPC_LOGGING … … 808 827 VBoxXPCOMIPCC_TEMPLATE = XPComIpcDll 809 828 VBoxXPCOMIPCC_INST = $(INST_BIN)components/ 810 #VBoxXPCOMIPCC_DEFS = HAVE_DEPENDENT_LIBS - dependentLibs.h is linux specific, so this cannot be required.811 829 VBoxXPCOMIPCC_SOURCES = \ 812 830 ipc/ipcd/client/src/ipcdclient.cpp \ … … 839 857 # DCONNECT daemon executable 840 858 # 841 VBoxXPCOMIPCD_TEMPLATE = XPComIpcExe 842 VBoxXPCOMIPCD_SOURCES = \ 843 ipc/ipcd/daemon/src/ipcd.cpp \ 844 ipc/ipcd/daemon/src/ipcClient.cpp \ 845 ipc/ipcd/daemon/src/ipcCommandModule.cpp \ 846 ipc/ipcd/daemon/src/ipcdUnix.cpp 859 ifdef VBOX_WITH_XPCOMIPCD_IN_VBOX_SVC 860 VBoxXPCOMIPCD_TEMPLATE = XPComIpcDll 861 VBoxXPCOMIPCD_SOURCES = \ 862 ipc/ipcd/daemon/src/ipcd.cpp \ 863 ipc/ipcd/daemon/src/ipcClient.cpp \ 864 ipc/ipcd/daemon/src/ipcCommandModule.cpp \ 865 ipc/ipcd/daemon/src/ipcdUnix.cpp 866 VBoxXPCOMIPCD_LIBS = \ 867 $(VBox-xpcom-ipcshared_1_TARGET) \ 868 $(VBoxXPCOM_1_TARGET) \ 869 $(TEMPLATE_XPComDll_LIBS) 870 else 871 VBoxXPCOMIPCD_TEMPLATE = XPComIpcExe 872 VBoxXPCOMIPCD_SOURCES = \ 873 ipc/ipcd/daemon/src/ipcd.cpp \ 874 ipc/ipcd/daemon/src/ipcClient.cpp \ 875 ipc/ipcd/daemon/src/ipcCommandModule.cpp \ 876 ipc/ipcd/daemon/src/ipcdUnix.cpp 877 endif 847 878 848 879 -
trunk/src/libs/xpcom18a4/ipc/ipcd/client/src/ipcdclient.cpp
r102470 r103300 1242 1242 { 1243 1243 char szPipeInheritFd[32]; RT_ZERO(szPipeInheritFd); 1244 const char *const s_apszArgs[] = { (char *const) path, "--inherit-startup-pipe", &szPipeInheritFd[0], NULL }; 1244 const char *const s_apszArgs[] = { (char *const) path, 1245 #ifdef VBOX_WITH_XPCOMIPCD_IN_VBOX_SVC 1246 "--auto-shutdown", 1247 #endif 1248 "--inherit-startup-pipe", 1249 &szPipeInheritFd[0], NULL }; 1245 1250 char c; 1246 1251 -
trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdPrivate.h
r103055 r103300 48 48 // XXX may want to make this more dynamic 49 49 // 50 #define IPC_MAX_CLIENTS 10000 50 #ifdef VBOX_WITH_XPCOMIPCD_IN_VBOX_SVC 51 # define IPC_MAX_CLIENTS 100 52 #else 53 # define IPC_MAX_CLIENTS 10000 54 #endif 51 55 52 56 /** List of connected IPC clients. */ -
trunk/src/libs/xpcom18a4/ipc/ipcd/daemon/src/ipcdUnix.cpp
r103116 r103300 37 37 #define LOG_GROUP LOG_GROUP_IPC 38 38 #include <iprt/assert.h> 39 #include <iprt/err core.h>39 #include <iprt/err.h> 40 40 #include <iprt/initterm.h> 41 41 #include <iprt/getopt.h> … … 44 44 #include <iprt/socket.h> 45 45 #include <iprt/string.h> 46 #ifdef VBOX_WITH_XPCOMIPCD_IN_VBOX_SVC 47 # include <iprt/thread.h> 48 #endif 46 49 #include <VBox/log.h> 47 50 … … 65 68 #include "ipcd.h" 66 69 70 71 /** 72 * The IPC daemon state 73 */ 74 typedef struct IPCDSTATE 75 { 76 RTSOCKET hSockListen; 77 int fdListen; 78 int ipcLockFD; 79 int ipcClientCount; 80 81 // 82 // the first element of this array is always zero; this is done so that the 83 // k'th element of ipcClientArray corresponds to the k'th element of 84 // ipcPollList. 85 // 86 ipcClient ipcClientArray[IPC_MAX_CLIENTS]; 87 88 RTPOLLSET hPollSet; 89 90 #ifdef VBOX_WITH_XPCOMIPCD_IN_VBOX_SVC 91 RTTHREAD hThread; 92 #endif 93 } IPCDSTATE; 94 typedef IPCDSTATE *PIPCDSTATE; 95 typedef const IPCDSTATE *PCIPCDSTATE; 96 97 67 98 //----------------------------------------------------------------------------- 68 99 // ipc directory and locking... 69 100 //----------------------------------------------------------------------------- 70 71 //72 // advisory file locking is used to ensure that only one IPC daemon is active73 // and bound to the local domain socket at a time.74 //75 // XXX this code does not work on OS/2.76 //77 #if !defined(XP_OS2)78 #define IPC_USE_FILE_LOCK79 #endif80 81 #ifdef IPC_USE_FILE_LOCK82 101 83 102 enum Status … … 89 108 }; 90 109 91 static int ipcLockFD = 0; 92 93 static Status AcquireDaemonLock(const char *baseDir) 110 static Status AcquireDaemonLock(PIPCDSTATE pThis, const char *baseDir) 94 111 { 95 112 const char lockName[] = "lock"; … … 100 117 + sizeof(lockName); // "lock" 101 118 102 #ifdef VBOX103 119 // 104 120 // Security checks for the directory … … 107 123 if (stat(baseDir, &st) == -1) 108 124 { 109 printf("Cannot stat '%s'.\n", baseDir);125 LogFlowFunc(("Cannot stat '%s'.\n", baseDir)); 110 126 return ELockFileOwner; 111 127 } … … 113 129 if (st.st_uid != getuid() && st.st_uid != geteuid()) 114 130 { 115 printf("Wrong owner (%d) of '%s'", st.st_uid, baseDir);131 LogFlowFunc(("Wrong owner (%d) of '%s'", st.st_uid, baseDir)); 116 132 if ( !stat("/tmp", &st) 117 133 && (st.st_mode & 07777) != 01777) 118 printf(" -- check /tmp permissions (%o should be 1777)\n",119 st.st_mode & 07777);120 printf(".\n");134 LogFlowFunc((" -- check /tmp permissions (%o should be 1777)\n", 135 st.st_mode & 07777)); 136 LogFlowFunc((".\n")); 121 137 return ELockFileOwner; 122 138 } … … 124 140 if (st.st_mode != (S_IRUSR | S_IWUSR | S_IXUSR | S_IFDIR)) 125 141 { 126 printf("Wrong mode (%o) of '%s'", st.st_mode, baseDir);142 LogFlowFunc(("Wrong mode (%o) of '%s'", st.st_mode, baseDir)); 127 143 if ( !stat("/tmp", &st) 128 144 && (st.st_mode & 07777) != 01777) 129 printf(" -- check /tmp permissions (%o should be 1777)\n",130 st.st_mode & 07777) ;131 printf(".\n");145 LogFlowFunc((" -- check /tmp permissions (%o should be 1777)\n", 146 st.st_mode & 07777)); 147 LogFlowFunc((".\n")); 132 148 return ELockFileOwner; 133 149 } 134 #endif135 150 136 151 char *lockFile = (char *) malloc(len); … … 142 157 // open lock file. it remains open until we shutdown. 143 158 // 144 ipcLockFD = open(lockFile, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR); 145 146 #ifndef VBOX 147 free(lockFile); 148 #endif 149 150 if (ipcLockFD == -1) 159 pThis->ipcLockFD = open(lockFile, O_WRONLY|O_CREAT, S_IWUSR|S_IRUSR); 160 if (pThis->ipcLockFD == -1) 151 161 { 152 162 free(lockFile); … … 154 164 } 155 165 156 #ifdef VBOX157 166 // 158 167 // Security checks for the lock file 159 168 // 160 if (fstat( ipcLockFD, &st) == -1)161 { 162 printf("Cannot stat '%s'.\n", lockFile);169 if (fstat(pThis->ipcLockFD, &st) == -1) 170 { 171 LogFlowFunc(("Cannot stat '%s'.\n", lockFile)); 163 172 free(lockFile); 164 173 return ELockFileOwner; … … 167 176 if (st.st_uid != getuid() && st.st_uid != geteuid()) 168 177 { 169 printf("Wrong owner (%d) of '%s'.\n", st.st_uid, lockFile);178 LogFlowFunc(("Wrong owner (%d) of '%s'.\n", st.st_uid, lockFile)); 170 179 free(lockFile); 171 180 return ELockFileOwner; … … 174 183 if (st.st_mode != (S_IRUSR | S_IWUSR | S_IFREG)) 175 184 { 176 printf("Wrong mode (%o) of '%s'.\n", st.st_mode, lockFile);185 LogFlowFunc(("Wrong mode (%o) of '%s'.\n", st.st_mode, lockFile)); 177 186 free(lockFile); 178 187 return ELockFileOwner; … … 180 189 181 190 free(lockFile); 182 #endif183 191 184 192 // … … 193 201 lock.l_len = 0; 194 202 lock.l_whence = SEEK_SET; 195 if (fcntl(ipcLockFD, F_SETLK, &lock) == -1) 203 if (fcntl(pThis->ipcLockFD, F_SETLK, &lock) == -1) 204 { 205 LogFlowFunc(("Setting lock failed -> %Rrc.\n", RTErrConvertFromErrno(errno))); 196 206 return ELockFileLock; 207 } 197 208 198 209 // 199 210 // truncate lock file once we have exclusive access to it. 200 211 // 201 ftruncate( ipcLockFD, 0);212 ftruncate(pThis->ipcLockFD, 0); 202 213 203 214 // … … 209 220 if (nb <= 0) 210 221 return ELockFileOpen; 211 write( ipcLockFD, buf, (size_t)nb);222 write(pThis->ipcLockFD, buf, (size_t)nb); 212 223 213 224 return EOk; 214 225 } 215 226 216 static Status InitDaemonDir( const char *socketPath)227 static Status InitDaemonDir(PIPCDSTATE pThis, const char *socketPath) 217 228 { 218 229 LogFlowFunc(("InitDaemonDir [sock=%s]\n", socketPath)); … … 232 243 // must be active, so bail. 233 244 // 234 Status status = AcquireDaemonLock( baseDir);245 Status status = AcquireDaemonLock(pThis, baseDir); 235 246 236 247 RTStrFree(baseDir); … … 243 254 } 244 255 245 static void ShutdownDaemonDir()246 {247 LogFlowFunc(("ShutdownDaemonDir\n"));248 249 // deleting directory and files underneath it allows another process250 // to think it has exclusive access. better to just leave the hidden251 // directory in /tmp and let the OS clean it up via the usual tmpdir252 // cleanup cron job.253 254 // this removes the advisory lock, allowing other processes to acquire it.255 if (ipcLockFD) {256 close(ipcLockFD);257 ipcLockFD = 0;258 }259 }260 261 #endif // IPC_USE_FILE_LOCK262 256 263 257 //----------------------------------------------------------------------------- … … 269 263 // 270 264 DECL_HIDDEN_DATA(RTLISTANCHOR) g_LstIpcClients; 271 static int ipcClientCount = 0;272 273 //274 // the first element of this array is always zero; this is done so that the275 // k'th element of ipcClientArray corresponds to the k'th element of276 // ipcPollList.277 //278 static ipcClient ipcClientArray[IPC_MAX_CLIENTS];279 280 265 static RTPOLLSET g_hPollSet = NIL_RTPOLLSET; 281 266 282 //----------------------------------------------------------------------------- 283 284 static int AddClient(RTPOLLSET hPollSet, RTSOCKET hSock) 285 { 286 if (ipcClientCount == IPC_MAX_CLIENTS) { 267 268 //----------------------------------------------------------------------------- 269 270 static int AddClient(PIPCDSTATE pThis, RTSOCKET hSock) 271 { 272 if (pThis->ipcClientCount == IPC_MAX_CLIENTS) { 287 273 LogFlowFunc(("reached maximum client limit\n")); 288 274 return -1; … … 290 276 291 277 /* Find an unused client entry. */ 292 for (uint32_t i = 0; i < RT_ELEMENTS( ipcClientArray); i++)293 { 294 if (! ipcClientArray[i].m_fUsed)278 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->ipcClientArray); i++) 279 { 280 if (!pThis->ipcClientArray[i].m_fUsed) 295 281 { 296 ipcClientArray[i].Init(i, hSock);297 ipcClientArray[i].m_fPollEvts = RTPOLL_EVT_READ;298 int vrc = RTPollSetAddSocket( hPollSet, hSock, RTPOLL_EVT_READ, i);282 pThis->ipcClientArray[i].Init(i, hSock); 283 pThis->ipcClientArray[i].m_fPollEvts = RTPOLL_EVT_READ; 284 int vrc = RTPollSetAddSocket(pThis->hPollSet, hSock, RTPOLL_EVT_READ, i); 299 285 if (RT_SUCCESS(vrc)) 300 286 { 301 RTListAppend(&g_LstIpcClients, & ipcClientArray[i].NdClients);302 ipcClientCount++;287 RTListAppend(&g_LstIpcClients, &pThis->ipcClientArray[i].NdClients); 288 pThis->ipcClientCount++; 303 289 return 0; 304 290 } 305 291 306 ipcClientArray[i].Finalize();292 pThis->ipcClientArray[i].Finalize(); 307 293 break; 308 294 } … … 313 299 } 314 300 315 static int RemoveClient( RTPOLLSET hPollSet, uint32_t idClient)316 { 317 int vrc = RTPollSetRemove( hPollSet, idClient);301 static int RemoveClient(PIPCDSTATE pThis, uint32_t idClient) 302 { 303 int vrc = RTPollSetRemove(pThis->hPollSet, idClient); 318 304 AssertRC(vrc); RT_NOREF(vrc); 319 305 320 RTListNodeRemove(& ipcClientArray[idClient].NdClients);321 ipcClientArray[idClient].Finalize();322 --ipcClientCount;306 RTListNodeRemove(&pThis->ipcClientArray[idClient].NdClients); 307 pThis->ipcClientArray[idClient].Finalize(); 308 pThis->ipcClientCount--; 323 309 return 0; 324 310 } … … 326 312 //----------------------------------------------------------------------------- 327 313 328 static void PollLoop( RTPOLLSET hPollSet, int fdListen)314 static void PollLoop(PIPCDSTATE pThis) 329 315 { 330 316 RTListInit(&g_LstIpcClients); … … 332 318 for (;;) 333 319 { 334 LogFlowFunc(("Polling [ipcClientCount=%d]\n", ipcClientCount));320 LogFlowFunc(("Polling [ipcClientCount=%d]\n", pThis->ipcClientCount)); 335 321 uint32_t idPoll = 0; 336 322 uint32_t fEvents = 0; 337 int vrc = RTPoll( hPollSet, 5 * RT_MS_1MIN, &fEvents, &idPoll);323 int vrc = RTPoll(pThis->hPollSet, 5 * RT_MS_1MIN, &fEvents, &idPoll); 338 324 if (RT_SUCCESS(vrc)) 339 325 { /* likely */ } … … 351 337 LogFlowFunc(("Got new connection\n")); 352 338 353 int fdClient = accept( fdListen, NULL, NULL);339 int fdClient = accept(pThis->fdListen, NULL, NULL); 354 340 if (fdClient == -1) 355 341 { … … 363 349 if (RT_SUCCESS(vrc)) 364 350 { 365 if (AddClient( hPollSet, hSock) != 0)351 if (AddClient(pThis, hSock) != 0) 366 352 RTSocketClose(hSock); 367 353 } … … 375 361 else 376 362 { 377 uint32_t fNewFlags = ipcClientArray[idPoll].Process(fEvents);363 uint32_t fNewFlags = pThis->ipcClientArray[idPoll].Process(fEvents); 378 364 if (!fNewFlags) 379 365 { 380 366 /* Cleanup dead client. */ 381 RemoveClient( hPollSet, idPoll);367 RemoveClient(pThis, idPoll); 382 368 383 369 /* Shutdown if no clients. */ 384 if ( ipcClientCount == 0)370 if (pThis->ipcClientCount == 0) 385 371 { 386 372 LogFlowFunc(("shutting down\n")); … … 388 374 } 389 375 } 390 else if ( ipcClientArray[idPoll].m_fPollEvts != fNewFlags)376 else if (pThis->ipcClientArray[idPoll].m_fPollEvts != fNewFlags) 391 377 { 392 378 /* Change flags. */ 393 vrc = RTPollSetEventsChange( hPollSet, idPoll, fNewFlags);379 vrc = RTPollSetEventsChange(pThis->hPollSet, idPoll, fNewFlags); 394 380 AssertRC(vrc); 395 ipcClientArray[idPoll].m_fPollEvts = fNewFlags;381 pThis->ipcClientArray[idPoll].m_fPollEvts = fNewFlags; 396 382 } 397 383 } … … 425 411 } 426 412 427 //----------------------------------------------------------------------------- 428 413 414 static int ipcdInit(PIPCDSTATE pThis, const char *pszSocketPath) 415 { 416 pThis->fdListen = 0; 417 pThis->hPollSet = NIL_RTPOLLSET; 418 pThis->hSockListen = NIL_RTSOCKET; 419 pThis->ipcLockFD = 0; 420 pThis->ipcClientCount = 0; 421 422 struct sockaddr_un addr; 423 memset(&addr, 0, sizeof(addr)); 424 addr.sun_family = AF_UNIX; 425 426 // set socket address 427 if (!pszSocketPath) 428 IPC_GetDefaultSocketPath(addr.sun_path, sizeof(addr.sun_path)); 429 else 430 RTStrCopy(addr.sun_path, sizeof(addr.sun_path), pszSocketPath); 431 432 Status status = InitDaemonDir(pThis, addr.sun_path); 433 if (status != EOk) { 434 if (status == ELockFileLock) 435 return VERR_ALREADY_EXISTS; 436 else 437 { 438 LogFlowFunc(("InitDaemonDir failed (status=%d)\n", status)); 439 // don't notify the parent to cause it to fail in PR_Read() after 440 // we terminate 441 if (status != ELockFileOwner) 442 printf(("Cannot create a lock file for '%s'.\n" 443 "Check permissions.\n", addr.sun_path)); 444 return VERR_INVALID_PARAMETER; 445 } 446 } 447 448 pThis->fdListen = socket(PF_UNIX, SOCK_STREAM, 0); 449 if (pThis->fdListen == -1) 450 { 451 LogFlowFunc(("socket failed [%d]\n", errno)); 452 return RTErrConvertFromErrno(errno); 453 } 454 455 if (bind(pThis->fdListen, (struct sockaddr *)&addr, sizeof(addr))) 456 { 457 LogFlowFunc(("bind failed [%d]\n", errno)); 458 return RTErrConvertFromErrno(errno); 459 } 460 461 // Use large backlog, as otherwise local sockets can reject connection 462 // attempts. Usually harmless, but causes an unnecessary start attempt 463 // of IPCD (which will terminate straight away), and the next attempt 464 // usually succeeds. But better avoid unnecessary activities. 465 if (listen(pThis->fdListen, 128)) 466 { 467 LogFlowFunc(("listen failed [%d]\n", errno)); 468 return RTErrConvertFromErrno(errno); 469 } 470 471 // Increase the file table size to 10240 or as high as possible. 472 struct rlimit lim; 473 if (getrlimit(RLIMIT_NOFILE, &lim) == 0) 474 { 475 if ( lim.rlim_cur < 10240 476 && lim.rlim_cur < lim.rlim_max) 477 { 478 lim.rlim_cur = lim.rlim_max <= 10240 ? lim.rlim_max : 10240; 479 if (setrlimit(RLIMIT_NOFILE, &lim) == -1) 480 LogFlowFunc(("WARNING: failed to increase file descriptor limit. (%d)\n", errno)); 481 } 482 } 483 else 484 LogFlowFunc(("WARNING: failed to obtain per-process file-descriptor limit (%d).\n", errno)); 485 486 int vrc = RTSocketFromNative(&pThis->hSockListen, pThis->fdListen); 487 if (RT_FAILURE(vrc)) 488 { 489 LogFlowFunc(("RTSocketFromNative() -> %Rrc\n", vrc)); 490 return vrc; 491 } 492 493 pThis->fdListen = (int)RTSocketToNative(pThis->hSockListen); 494 495 vrc = RTPollSetCreate(&pThis->hPollSet); 496 if (RT_FAILURE(vrc)) 497 { 498 LogFlowFunc(("RTPollSetCreate() -> %Rrc\n", vrc)); 499 return vrc; 500 } 501 502 g_hPollSet = pThis->hPollSet; 503 504 vrc = RTPollSetAddSocket(pThis->hPollSet, pThis->hSockListen, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, UINT32_MAX - 1); 505 if (RT_FAILURE(vrc)) 506 { 507 LogFlowFunc(("RTPollSetAddSocket() -> %Rrc\n", vrc)); 508 return vrc; 509 } 510 511 return VINF_SUCCESS; 512 } 513 514 515 static void ipcdTerm(PIPCDSTATE pThis) 516 { 517 Assert(pThis->ipcClientCount == 0); 518 519 // it is critical that we release the lock before closing the socket, 520 // otherwise, a client might launch another daemon that would be unable 521 // to acquire the lock and would then leave the client without a daemon. 522 523 // deleting directory and files underneath it allows another process 524 // to think it has exclusive access. better to just leave the hidden 525 // directory in /tmp and let the OS clean it up via the usual tmpdir 526 // cleanup cron job. 527 528 // this removes the advisory lock, allowing other processes to acquire it. 529 if (pThis->ipcLockFD) { 530 close(pThis->ipcLockFD); 531 pThis->ipcLockFD = 0; 532 } 533 534 int vrc = VINF_SUCCESS; 535 if (pThis->hPollSet != NIL_RTPOLLSET) 536 { 537 vrc = RTPollSetDestroy(pThis->hPollSet); 538 AssertRC(vrc); 539 pThis->hPollSet = NIL_RTPOLLSET; 540 } 541 542 if (pThis->hSockListen != NIL_RTSOCKET) 543 { 544 vrc = RTSocketClose(pThis->hSockListen); 545 AssertRC(vrc); 546 pThis->hSockListen = NIL_RTSOCKET; 547 } 548 } 549 550 551 //----------------------------------------------------------------------------- 552 #ifndef VBOX_WITH_XPCOMIPCD_IN_VBOX_SVC 429 553 int main(int argc, char **argv) 430 554 { … … 482 606 //IPC_Sleep(2); 483 607 484 struct sockaddr_un addr; 485 memset(&addr, 0, sizeof(addr)); 486 addr.sun_family = AF_UNIX; 487 488 // set socket address 489 if (!pszSocketPath) 490 IPC_GetDefaultSocketPath(addr.sun_path, sizeof(addr.sun_path)); 491 else 492 RTStrCopy(addr.sun_path, sizeof(addr.sun_path), pszSocketPath); 493 494 #ifdef IPC_USE_FILE_LOCK 495 Status status = InitDaemonDir(addr.sun_path); 496 if (status != EOk) { 497 if (status == ELockFileLock) { 498 LogFlowFunc(("Another daemon is already running, exiting.\n")); 499 // send a signal to the blocked parent to indicate success 500 IPC_NotifyParent(uStartupPipeFd); 501 return 0; 502 } 503 else { 504 LogFlowFunc(("InitDaemonDir failed (status=%d)\n", status)); 505 // don't notify the parent to cause it to fail in PR_Read() after 506 // we terminate 507 if (status != ELockFileOwner) 508 printf("Cannot create a lock file for '%s'.\n" 509 "Check permissions.\n", addr.sun_path); 510 return 0; 511 } 512 } 608 IPCDSTATE IpcdState; 609 vrc = ipcdInit(&IpcdState, pszSocketPath); 610 if (vrc == VERR_ALREADY_EXISTS) 611 { 612 IPC_NotifyParent(uStartupPipeFd); 613 return 0; 614 } 615 616 if (RT_SUCCESS(vrc)) 617 { 618 IPC_NotifyParent(uStartupPipeFd); 619 PollLoop(&IpcdState); 620 } 621 622 ipcdTerm(&IpcdState); 623 return 0; 624 } 625 626 #else 627 628 static DECLCALLBACK(int) ipcdThread(RTTHREAD hThreadSelf, void *pvUser) 629 { 630 IPCDSTATE IpcdState; 631 632 int vrc = ipcdInit(&IpcdState, NULL /*pszSocketPath*/); 633 *(int *)pvUser = vrc; /* Set the startup status code. */ 634 RTThreadUserSignal(hThreadSelf); 635 636 if (RT_SUCCESS(vrc)) 637 PollLoop(&IpcdState); 638 639 ipcdTerm(&IpcdState); 640 return VINF_SUCCESS; 641 } 642 643 644 DECL_EXPORT_NOTHROW(int) RTCALL VBoxXpcomIpcdCreate(PRTTHREAD phThrdIpcd) 645 { 646 int vrcThrdStartup = VINF_SUCCESS; 647 int vrc = RTThreadCreate(phThrdIpcd, ipcdThread, &vrcThrdStartup, 0 /*cbStack*/, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "IPCD-Msg"); 648 if (RT_FAILURE(vrc)) 649 return vrc; 650 651 vrc = RTThreadUserWait(*phThrdIpcd, RT_MS_30SEC); 652 AssertRCReturn(vrc, vrc); 653 654 if (RT_FAILURE(vrcThrdStartup)) 655 { 656 /* Wait for the thread to terminate. */ 657 vrc = RTThreadWait(*phThrdIpcd, RT_MS_30SEC, NULL /*prc*/); 658 AssertRC(vrc); 659 *phThrdIpcd = NIL_RTTHREAD; 660 LogFlowFunc(("Creating daemon failed -> %Rrc\n", vrcThrdStartup)); 661 return vrcThrdStartup; 662 } 663 664 return VINF_SUCCESS; 665 } 666 667 668 DECL_EXPORT_NOTHROW(int) RTCALL VBoxXpcomIpcdDestroy(RTTHREAD hThrdIpcd) 669 { 670 /* Normally just need to wait as this will get called when the last client has exited and VBoxSVC is shutting down. */ 671 int vrcThrd = VINF_SUCCESS; 672 int vrc = RTThreadWait(hThrdIpcd, RT_MS_30SEC, &vrcThrd); 673 if (RT_FAILURE(vrc)) 674 return vrc; 675 676 return vrcThrd; 677 } 513 678 #endif 514 515 int fdListen = socket(PF_UNIX, SOCK_STREAM, 0);516 if (fdListen == -1)517 LogFlowFunc(("socket failed [%d]\n", errno));518 else519 {520 if (bind(fdListen, (struct sockaddr *)&addr, sizeof(addr)) == 0)521 {522 // Use large backlog, as otherwise local sockets can reject connection523 // attempts. Usually harmless, but causes an unnecessary start attempt524 // of IPCD (which will terminate straight away), and the next attempt525 // usually succeeds. But better avoid unnecessary activities.526 if (listen(fdListen, 128) == 0)527 {528 IPC_NotifyParent(uStartupPipeFd);529 530 #if defined(VBOX) && !defined(XP_OS2)531 // Increase the file table size to 10240 or as high as possible.532 struct rlimit lim;533 if (getrlimit(RLIMIT_NOFILE, &lim) == 0)534 {535 if ( lim.rlim_cur < 10240536 && lim.rlim_cur < lim.rlim_max)537 {538 lim.rlim_cur = lim.rlim_max <= 10240 ? lim.rlim_max : 10240;539 if (setrlimit(RLIMIT_NOFILE, &lim) == -1)540 printf("WARNING: failed to increase file descriptor limit. (%d)\n", errno);541 }542 }543 else544 printf("WARNING: failed to obtain per-process file-descriptor limit (%d).\n", errno);545 #endif546 547 RTSOCKET hSockListen;548 int vrc = RTSocketFromNative(&hSockListen, fdListen);549 if (RT_SUCCESS(vrc))550 {551 fdListen = (int)RTSocketToNative(hSockListen);552 553 RTPOLLSET hPollSet = NIL_RTPOLLSET;554 vrc = RTPollSetCreate(&hPollSet);555 if (RT_SUCCESS(vrc))556 {557 g_hPollSet = hPollSet;558 559 vrc = RTPollSetAddSocket(hPollSet, hSockListen, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, UINT32_MAX - 1);560 if (RT_SUCCESS(vrc))561 PollLoop(hPollSet, fdListen);562 else563 LogFlowFunc(("RTPollSetCreate() -> %Rrc\n", vrc));564 }565 else566 LogFlowFunc(("RTPollSetCreate() -> %Rrc\n", vrc));567 568 vrc = RTPollSetDestroy(hPollSet);569 AssertRC(vrc);570 }571 else572 LogFlowFunc(("RTSocketFromNative() -> %Rrc\n", vrc));573 574 vrc = RTSocketClose(hSockListen);575 AssertRC(vrc);576 fdListen = -1;577 }578 else579 LogFlowFunc(("listen failed [%d]\n", errno));580 }581 else582 LogFlowFunc(("bind failed [%d]\n", errno));583 584 LogFlowFunc(("closing socket\n"));585 if (fdListen != -1)586 close(fdListen);587 }588 589 //IPC_Sleep(5);590 591 #ifdef IPC_USE_FILE_LOCK592 // it is critical that we release the lock before closing the socket,593 // otherwise, a client might launch another daemon that would be unable594 // to acquire the lock and would then leave the client without a daemon.595 596 ShutdownDaemonDir();597 #endif598 599 return 0;600 }
Note:
See TracChangeset
for help on using the changeset viewer.