PollableEvent::PollableEvent() : mWriteFD(nullptr) , mReadFD(nullptr) , mSignaled(false) { MOZ_COUNT_CTOR(PollableEvent); MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); // create pair of prfiledesc that can be used as a poll()ble // signal. on windows use a localhost socket pair, and on // unix use a pipe. #ifdef USEPIPE SOCKET_LOG(("PollableEvent() using pipe\n")); if (PR_CreatePipe(&mReadFD, &mWriteFD) == PR_SUCCESS) { // make the pipe non blocking. NSPR asserts at // trying to use SockOpt here PROsfd fd = PR_FileDesc2NativeHandle(mReadFD); int flags = fcntl(fd, F_GETFL, 0); (void)fcntl(fd, F_SETFL, flags | O_NONBLOCK); fd = PR_FileDesc2NativeHandle(mWriteFD); flags = fcntl(fd, F_GETFL, 0); (void)fcntl(fd, F_SETFL, flags | O_NONBLOCK); } else { mReadFD = nullptr; mWriteFD = nullptr; SOCKET_LOG(("PollableEvent() pipe failed\n")); } #else SOCKET_LOG(("PollableEvent() using socket pair\n")); PRFileDesc *fd[2]; LazyInitSocket(); if (NewTCPSocketPair(fd)) { mReadFD = fd[0]; mWriteFD = fd[1]; // compatibility with LSPs such as McAfee that assume a NSPR // layer for read ala the nspr Pollable Event - Bug 698882. This layer is a nop. PRFileDesc *topLayer = PR_CreateIOLayerStub(sPollableEventLayerIdentity, sPollableEventLayerMethodsPtr); if (topLayer) { if (PR_PushIOLayer(fd[0], PR_TOP_IO_LAYER, topLayer) == PR_FAILURE) { topLayer->dtor(topLayer); } else { SOCKET_LOG(("PollableEvent() nspr layer ok\n")); mReadFD = topLayer; } } } else { SOCKET_LOG(("PollableEvent() socketpair failed\n")); } #endif if (mReadFD && mWriteFD) { // prime the system to deal with races invovled in [dc]tor cycle SOCKET_LOG(("PollableEvent() ctor ok\n")); mSignaled = true; PR_Write(mWriteFD, "I", 1); } }
static PRFileDesc *PopLayer(PRFileDesc *stack) { PRFileDesc *popped = PR_PopIOLayer(stack, identity); if (verbosity > quiet) PR_fprintf(logFile, "Popped layer(0x%x) from stack(0x%x)\n", popped, stack); popped->dtor(popped); return stack; } /* PopLayer */
static PRStatus nsNetMon_Close(PRFileDesc *fd) { if (!fd) { return PR_FAILURE; } NetworkActivityMonitor::UnregisterFd(fd); PRFileDesc* layer = PR_PopIOLayer(fd, PR_TOP_IO_LAYER); MOZ_RELEASE_ASSERT(layer && layer->identity == sNetActivityMonitorLayerIdentity, "NetActivityMonitor Layer not on top of stack"); layer->dtor(layer); return fd->methods->close(fd); }
static PRStatus TcpUdpPRCloseLayerClose(PRFileDesc *aFd) { if (!aFd) { return PR_FAILURE; } PRFileDesc* layer = PR_PopIOLayer(aFd, PR_TOP_IO_LAYER); MOZ_RELEASE_ASSERT(layer && layer->identity == sTcpUdpPRCloseLayerId, "Closing Layer not on top of stack"); ClosingLayerSecret *closingLayerSecret = reinterpret_cast<ClosingLayerSecret *>(layer->secret); PRStatus status = PR_SUCCESS; if (aFd) { // If this is called during shutdown do not call ..method->close(fd) and // let it leak. if (gIOService->IsShutdown()) { // If the ClosingService layer is the first layer above PR_NSPR_IO_LAYER // we are not going to leak anything, but the PR_Close will not be called. PR_Free(aFd); } else if (closingLayerSecret->mClosingService) { closingLayerSecret->mClosingService->PostRequest(aFd); } else { // Socket is created before closing service has been started or there was // a problem with starting it. PR_Close(aFd); } } layer->secret = nullptr; layer->dtor(layer); delete closingLayerSecret; return status; }
PollableEvent::PollableEvent() : mWriteFD(nullptr) , mReadFD(nullptr) , mSignaled(false) { MOZ_COUNT_CTOR(PollableEvent); MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); // create pair of prfiledesc that can be used as a poll()ble // signal. on windows use a localhost socket pair, and on // unix use a pipe. #ifdef USEPIPE SOCKET_LOG(("PollableEvent() using pipe\n")); if (PR_CreatePipe(&mReadFD, &mWriteFD) == PR_SUCCESS) { // make the pipe non blocking. NSPR asserts at // trying to use SockOpt here PROsfd fd = PR_FileDesc2NativeHandle(mReadFD); int flags = fcntl(fd, F_GETFL, 0); (void)fcntl(fd, F_SETFL, flags | O_NONBLOCK); fd = PR_FileDesc2NativeHandle(mWriteFD); flags = fcntl(fd, F_GETFL, 0); (void)fcntl(fd, F_SETFL, flags | O_NONBLOCK); } else { mReadFD = nullptr; mWriteFD = nullptr; SOCKET_LOG(("PollableEvent() pipe failed\n")); } #else SOCKET_LOG(("PollableEvent() using socket pair\n")); PRFileDesc *fd[2]; LazyInitSocket(); // Try with a increased recv buffer first (bug 1248358). if (NewTCPSocketPair(fd, true)) { mReadFD = fd[0]; mWriteFD = fd[1]; // If the previous fails try without recv buffer increase (bug 1305436). } else if (NewTCPSocketPair(fd, false)) { mReadFD = fd[0]; mWriteFD = fd[1]; // If both fail, try the old version. } else if (PR_NewTCPSocketPair(fd) == PR_SUCCESS) { mReadFD = fd[0]; mWriteFD = fd[1]; PRSocketOptionData socket_opt; DebugOnly<PRStatus> status; socket_opt.option = PR_SockOpt_NoDelay; socket_opt.value.no_delay = true; PR_SetSocketOption(mWriteFD, &socket_opt); PR_SetSocketOption(mReadFD, &socket_opt); socket_opt.option = PR_SockOpt_Nonblocking; socket_opt.value.non_blocking = true; status = PR_SetSocketOption(mWriteFD, &socket_opt); MOZ_ASSERT(status == PR_SUCCESS); status = PR_SetSocketOption(mReadFD, &socket_opt); MOZ_ASSERT(status == PR_SUCCESS); } if (mReadFD && mWriteFD) { // compatibility with LSPs such as McAfee that assume a NSPR // layer for read ala the nspr Pollable Event - Bug 698882. This layer is a nop. PRFileDesc *topLayer = PR_CreateIOLayerStub(sPollableEventLayerIdentity, sPollableEventLayerMethodsPtr); if (topLayer) { if (PR_PushIOLayer(fd[0], PR_TOP_IO_LAYER, topLayer) == PR_FAILURE) { topLayer->dtor(topLayer); } else { SOCKET_LOG(("PollableEvent() nspr layer ok\n")); mReadFD = topLayer; } } } else { SOCKET_LOG(("PollableEvent() socketpair failed\n")); } #endif if (mReadFD && mWriteFD) { // prime the system to deal with races invovled in [dc]tor cycle SOCKET_LOG(("PollableEvent() ctor ok\n")); mSignaled = true; PR_Write(mWriteFD, "I", 1); } }