static bool SpawnIOChild(char* const* aArgs, PRProcess** aPID, PRFileDesc** aFromChildFD, PRFileDesc** aToChildFD) { PRFileDesc* toChildPipeRead; PRFileDesc* toChildPipeWrite; if (PR_CreatePipe(&toChildPipeRead, &toChildPipeWrite) != PR_SUCCESS) return false; PR_SetFDInheritable(toChildPipeRead, true); PR_SetFDInheritable(toChildPipeWrite, false); PRFileDesc* fromChildPipeRead; PRFileDesc* fromChildPipeWrite; if (PR_CreatePipe(&fromChildPipeRead, &fromChildPipeWrite) != PR_SUCCESS) { PR_Close(toChildPipeRead); PR_Close(toChildPipeWrite); return false; } PR_SetFDInheritable(fromChildPipeRead, false); PR_SetFDInheritable(fromChildPipeWrite, true); PRProcessAttr* attr = PR_NewProcessAttr(); if (!attr) { PR_Close(fromChildPipeRead); PR_Close(fromChildPipeWrite); PR_Close(toChildPipeRead); PR_Close(toChildPipeWrite); return false; } PR_ProcessAttrSetStdioRedirect(attr, PR_StandardInput, toChildPipeRead); PR_ProcessAttrSetStdioRedirect(attr, PR_StandardOutput, fromChildPipeWrite); PRProcess* process = PR_CreateProcess(aArgs[0], aArgs, nullptr, attr); PR_DestroyProcessAttr(attr); PR_Close(fromChildPipeWrite); PR_Close(toChildPipeRead); if (!process) { LOG(("ntlm_auth exec failure [%d]", PR_GetError())); PR_Close(fromChildPipeRead); PR_Close(toChildPipeWrite); return false; } *aPID = process; *aFromChildFD = fromChildPipeRead; *aToChildFD = toChildPipeWrite; return true; }
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 int e_prpipe (PRFileDesc **fds) { #ifdef G_OS_WIN32 if (PR_NewTCPSocketPair (fds) != PR_FAILURE) return 0; #else if (PR_CreatePipe (&fds[0], &fds[1]) != PR_FAILURE) return 0; #endif fds[0] = NULL; fds[1] = NULL; return -1; }
/* Create a half duplex nspr pipe */ void wrap_PR_CreatePipe(const char* msg, PRFileDesc **readPipe, PRFileDesc **writePipe) { /* We could use the TCPSocketPair to get a full duplex channel but there was a comment in prio.h (the nspr header) about whether TCPSocketPair is implemented on all platforms */ PR_CreatePipe(readPipe, writePipe); if (tracing) { int readfd = PRFileDesc_To_FD(*readPipe); int writefd = PRFileDesc_To_FD(*readPipe); int readflags = fcntl(readfd, F_GETFL); int writeflags = fcntl(writefd, F_GETFL); trace("Created pipe %s read=%d write=%d\n", msg, readfd, writefd); trace(" read flags=%X write flags=%X\n", readflags, writeflags); } }
void SocketTransportServiceTest::SetUp() { // Get the transport service as a dispatch target nsresult rv; target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); ASSERT_TRUE(NS_SUCCEEDED(rv)); // Get the transport service as a transport service stservice_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); ASSERT_TRUE(NS_SUCCEEDED(rv)); // Create a loopback pipe PRStatus status = PR_CreatePipe(&readpipe_, &writepipe_); ASSERT_EQ(status, PR_SUCCESS); // Register ourselves as a listener for the read side of the // socket. The registration has to happen on the STS thread, // hence this event stuff. rv = target_->Dispatch(new RegisterEvent(this), 0); ASSERT_TRUE(NS_SUCCEEDED(rv)); ASSERT_TRUE_WAIT(registered_, 10000); }
static nsresult vboxsvcSpawnDaemon(void) { PRFileDesc *readable = nsnull, *writable = nsnull; PRProcessAttr *attr = nsnull; nsresult rv = NS_ERROR_FAILURE; PRFileDesc *devNull; // The ugly casts are necessary because the PR_CreateProcessDetached has // a const array of writable strings as a parameter. It won't write. */ char * const args[] = { (char *)VBoxSVCPath, (char *)"--auto-shutdown", 0 }; // Use a pipe to determine when the daemon process is in the position // to actually process requests. The daemon will write "READY" to the pipe. if (PR_CreatePipe(&readable, &writable) != PR_SUCCESS) goto end; PR_SetFDInheritable(writable, PR_TRUE); attr = PR_NewProcessAttr(); if (!attr) goto end; if (PR_ProcessAttrSetInheritableFD(attr, writable, VBOXSVC_STARTUP_PIPE_NAME) != PR_SUCCESS) goto end; devNull = PR_Open("/dev/null", PR_RDWR, 0); if (!devNull) goto end; PR_ProcessAttrSetStdioRedirect(attr, PR_StandardInput, devNull); PR_ProcessAttrSetStdioRedirect(attr, PR_StandardOutput, devNull); PR_ProcessAttrSetStdioRedirect(attr, PR_StandardError, devNull); if (PR_CreateProcessDetached(VBoxSVCPath, args, nsnull, attr) != PR_SUCCESS) goto end; // Close /dev/null PR_Close(devNull); // Close the child end of the pipe to make it the only owner of the // file descriptor, so that unexpected closing can be detected. PR_Close(writable); writable = nsnull; char msg[10]; RT_ZERO(msg); if ( PR_Read(readable, msg, sizeof(msg)-1) != 5 || strcmp(msg, "READY")) { /* If several clients start VBoxSVC simultaneously only one can * succeed. So treat this as success as well. */ rv = NS_OK; goto end; } rv = NS_OK; end: if (readable) PR_Close(readable); if (writable) PR_Close(writable); if (attr) PR_DestroyProcessAttr(attr); return rv; }
JD_METHOD_(JDBool) CNSAdapter_NSPR::JD_CreatePipe(void** readPipe, void** writePipe) { return PR_CreatePipe((PRFileDesc**)readPipe, (PRFileDesc**)writePipe); }
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); } }
nsresult sbProcess::Run() { PRStatus status; nsresult rv; // Set up to auto-kill process. sbAutoKillProcess autoSelf(this); // Operate under the process lock. { NS_ENSURE_TRUE(mProcessLock, NS_ERROR_NOT_INITIALIZED); nsAutoLock autoProcessLock(mProcessLock); // Get the number of arguments. PRUint32 argCount = mArgList.Length(); NS_ENSURE_TRUE(argCount > 0, NS_ERROR_ILLEGAL_VALUE); // Convert the UTF-16 argument list to a UTF-8 argument list. nsTArray<nsCString> argListUTF8; for (PRUint32 i = 0; i < argCount; i++) { NS_ENSURE_TRUE(argListUTF8.AppendElement (NS_ConvertUTF16toUTF8(mArgList[i])), NS_ERROR_OUT_OF_MEMORY); } // Allocate a null-terminated char* argument list and set it up for // auto-disposal. char** argList = reinterpret_cast<char**> (NS_Alloc((argCount + 1) * sizeof(char*))); NS_ENSURE_TRUE(argList, NS_ERROR_OUT_OF_MEMORY); sbAutoNSTypePtr<char*> autoArgList(argList); // Convert the argument list to a null-terminated char* argument list. for (PRUint32 i = 0; i < argCount; i++) { argList[i] = const_cast<char*>(argListUTF8[i].get()); } argList[argCount] = NULL; // Set up the process attributes and set them up for auto-disposal. PRProcessAttr* processAttr = PR_NewProcessAttr(); NS_ENSURE_TRUE(processAttr, NS_ERROR_FAILURE); sbAutoPRProcessAttr autoProcessAttr(processAttr); // Set up process stdin. if (mPipeStdinString) { // Create a process stdin pipe and set it up for auto-disposal. PRFileDesc* stdinReadFD; PRFileDesc* stdinWriteFD; status = PR_CreatePipe(&stdinReadFD, &stdinWriteFD); NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE); sbAutoPRFileDesc autoStdinReadFD(stdinReadFD); sbAutoPRFileDesc autoStdinWriteFD(stdinWriteFD); // Set up stdin pipe file descriptors. status = PR_SetFDInheritable(stdinReadFD, PR_TRUE); NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE); status = PR_SetFDInheritable(stdinWriteFD, PR_FALSE); NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE); // Fill pipe. nsCAutoString writeData = NS_ConvertUTF16toUTF8(mStdinString); PRInt32 bytesWritten; bytesWritten = PR_Write(stdinWriteFD, writeData.get(), writeData.Length()); NS_ENSURE_TRUE(bytesWritten == writeData.Length(), NS_ERROR_FAILURE); // Redirect process stdin. PR_ProcessAttrSetStdioRedirect(processAttr, PR_StandardInput, stdinReadFD); // Keep stdin read descriptor open for the process to read. Close the // stdin write descriptor so that the process gets EOF when all of the // data is read. mStdinReadFD = autoStdinReadFD.forget(); PR_Close(autoStdinWriteFD.forget()); } // Set up process stdout. if (mPipeStdoutString) { // Create a process stdout pipe and set it up for auto-disposal. PRFileDesc* stdoutReadFD; PRFileDesc* stdoutWriteFD; status = PR_CreatePipe(&stdoutReadFD, &stdoutWriteFD); NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE); sbAutoPRFileDesc autoStdoutReadFD(stdoutReadFD); sbAutoPRFileDesc autoStdoutWriteFD(stdoutWriteFD); // Set up stdout pipe file descriptors. status = PR_SetFDInheritable(stdoutReadFD, PR_FALSE); NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE); status = PR_SetFDInheritable(stdoutWriteFD, PR_TRUE); NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE); // Redirect process stdout. PR_ProcessAttrSetStdioRedirect(processAttr, PR_StandardOutput, stdoutWriteFD); // Keep descriptors. mStdoutReadFD = autoStdoutReadFD.forget(); mStdoutWriteFD = autoStdoutWriteFD.forget(); } // Create and start running the process. mBaseProcess = PR_CreateProcess(argList[0], argList, NULL, processAttr); NS_ENSURE_TRUE(mBaseProcess, NS_ERROR_FAILURE); // Wait for process done on another thread. nsCOMPtr<nsIRunnable> runnable = NS_NEW_RUNNABLE_METHOD(sbProcess, this, WaitForDone); NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY); rv = NS_NewThread(getter_AddRefs(mWaitForDoneThread), runnable); NS_ENSURE_SUCCESS(rv, rv); } // Clear process auto-kill. autoSelf.forget(); return NS_OK; }