static void tstRTPipe5(void) { RTTestISub("Inherit non-standard pipe handle, read end"); char szPathSelf[RTPATH_MAX]; RTTESTI_CHECK_RETV(RTProcGetExecutablePath(szPathSelf, sizeof(szPathSelf)) == szPathSelf); RTPIPE hPipeR; RTPIPE hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_READ), VINF_SUCCESS); RTHCINTPTR hNative = RTPipeToNative(hPipeR); RTTESTI_CHECK_RETV(hNative != -1); char szNative[64]; RTStrPrintf(szNative, sizeof(szNative), "%RHi", hNative); const char *papszArgs[4] = { szPathSelf, "--child-5", szNative, NULL }; RTPROCESS hChild; RTTESTI_CHECK_RC_RETV(RTProcCreate(szPathSelf, papszArgs, RTENV_DEFAULT, 0 /*fFlags*/, &hChild), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeW, g_szTest5Message, sizeof(g_szTest5Message) - 1, NULL), VINF_SUCCESS); int rc; RTTESTI_CHECK_RC(rc = RTPipeClose(hPipeW), VINF_SUCCESS); if (RT_FAILURE(rc)) RTTESTI_CHECK_RC(RTProcTerminate(hChild), VINF_SUCCESS); RTPROCSTATUS ProcStatus; RTTESTI_CHECK_RC(rc = RTProcWait(hChild, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); if (RT_FAILURE(rc)) return; RTTESTI_CHECK( ProcStatus.enmReason == RTPROCEXITREASON_NORMAL && ProcStatus.iStatus == 0); }
/** * Destruct a host parallel driver instance. * * Most VM resources are freed by the VM. This callback is provided so that * any non-VM resources can be freed correctly. * * @param pDrvIns The driver instance data. */ static DECLCALLBACK(void) drvHostParallelDestruct(PPDMDRVINS pDrvIns) { PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL); LogFlowFunc(("iInstance=%d\n", pDrvIns->iInstance)); PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns); #ifndef VBOX_WITH_WIN_PARPORT_SUP int rc; if (pThis->hFileDevice != NIL_RTFILE) ioctl(RTFileToNative(pThis->hFileDevice), PPRELEASE); rc = RTPipeClose(pThis->hWakeupPipeW); AssertRC(rc); pThis->hWakeupPipeW = NIL_RTPIPE; rc = RTPipeClose(pThis->hWakeupPipeR); AssertRC(rc); pThis->hWakeupPipeR = NIL_RTPIPE; rc = RTFileClose(pThis->hFileDevice); AssertRC(rc); /** @todo r=bird: Why aren't this closed on Windows? */ pThis->hFileDevice = NIL_RTFILE; if (pThis->pszDevicePath) { MMR3HeapFree(pThis->pszDevicePath); pThis->pszDevicePath = NULL; } #endif /* VBOX_WITH_WIN_PARPORT_SUP */ }
/** * Stop all service threads and free the device chain. */ USBProxyBackendUsbIp::~USBProxyBackendUsbIp() { LogFlowThisFunc(("\n")); /* * Stop the service. */ if (isActive()) stop(); /* * Free resources. */ if (m->hPollSet != NIL_RTPOLLSET) { disconnect(); int rc = RTPollSetRemove(m->hPollSet, USBIP_POLL_ID_PIPE); AssertRC(rc); rc = RTPollSetDestroy(m->hPollSet); AssertRC(rc); rc = RTPipeClose(m->hWakeupPipeR); AssertRC(rc); rc = RTPipeClose(m->hWakeupPipeW); AssertRC(rc); } if (m->pszHost) RTStrFree(m->pszHost); if (m->hMtxDevices != NIL_RTSEMFASTMUTEX) RTSemFastMutexDestroy(m->hMtxDevices); delete m; }
static void tstRTPipe2(void) { RTTestISub("Negative"); RTPIPE hPipeR = (RTPIPE)1; RTPIPE hPipeW = (RTPIPE)1; RTTESTI_CHECK_RC(RTPipeCreate(&hPipeR, &hPipeW, ~0), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTPipeCreate(NULL, &hPipeW, 0), VERR_INVALID_POINTER); RTTESTI_CHECK_RC(RTPipeCreate(&hPipeR, NULL, 0), VERR_INVALID_POINTER); RTTESTI_CHECK(hPipeR == (RTPIPE)1); RTTESTI_CHECK(hPipeW == (RTPIPE)1); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); char abBuf[_4K]; size_t cbRead = ~(size_t)3; RTTESTI_CHECK_RC(RTPipeRead(hPipeW, abBuf, 0, &cbRead), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeRead(hPipeW, abBuf, 1, &cbRead), VERR_ACCESS_DENIED); RTTESTI_CHECK(cbRead == ~(size_t)3); RTTESTI_CHECK_RC(RTPipeReadBlocking(hPipeW, abBuf, 0, NULL), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeReadBlocking(hPipeW, abBuf, 1, NULL), VERR_ACCESS_DENIED); size_t cbWrite = ~(size_t)5; RTTESTI_CHECK_RC(RTPipeWrite(hPipeR, "asdf", 0, &cbWrite), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeWrite(hPipeR, "asdf", 4, &cbWrite), VERR_ACCESS_DENIED); RTTESTI_CHECK(cbWrite == ~(size_t)5); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeR, "asdf", 0, NULL), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeR, "asdf", 4, NULL), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeFlush(hPipeR), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); }
/** * Reads from a pipe. * * @returns @a rc or other status code. * @param rc The current status of the operation. Error status * are preserved and returned. * @param phPipeR Pointer to the pipe handle. * @param pcbAllocated Pointer to the buffer size variable. * @param poffCur Pointer to the buffer offset variable. * @param ppszBuffer Pointer to the buffer pointer variable. */ static int rtProcProcessOutput(int rc, PRTPIPE phPipeR, size_t *pcbAllocated, size_t *poffCur, char **ppszBuffer, RTPOLLSET hPollSet, uint32_t idPollSet) { size_t cbRead; char szTmp[_4K - 1]; for (;;) { int rc2 = RTPipeRead(*phPipeR, szTmp, sizeof(szTmp), &cbRead); if (RT_SUCCESS(rc2) && cbRead) { /* Resize the buffer. */ if (*poffCur + cbRead >= *pcbAllocated) { if (*pcbAllocated >= _1G) { RTPollSetRemove(hPollSet, idPollSet); rc2 = RTPipeClose(*phPipeR); AssertRC(rc2); *phPipeR = NIL_RTPIPE; return RT_SUCCESS(rc) ? VERR_TOO_MUCH_DATA : rc; } size_t cbNew = *pcbAllocated ? *pcbAllocated * 2 : sizeof(szTmp) + 1; Assert(*poffCur + cbRead < cbNew); rc2 = RTStrRealloc(ppszBuffer, cbNew); if (RT_FAILURE(rc2)) { RTPollSetRemove(hPollSet, idPollSet); rc2 = RTPipeClose(*phPipeR); AssertRC(rc2); *phPipeR = NIL_RTPIPE; return RT_SUCCESS(rc) ? rc2 : rc; } *pcbAllocated = cbNew; } /* Append the new data, terminating it. */ memcpy(*ppszBuffer + *poffCur, szTmp, cbRead); *poffCur += cbRead; (*ppszBuffer)[*poffCur] = '\0'; /* Check for null terminators in the string. */ if (RT_SUCCESS(rc) && memchr(szTmp, '\0', cbRead)) rc = VERR_NO_TRANSLATION; /* If we read a full buffer, try read some more. */ if (RT_SUCCESS(rc) && cbRead == sizeof(szTmp)) continue; } else if (rc2 != VINF_TRY_AGAIN) { if (RT_FAILURE(rc) && rc2 != VERR_BROKEN_PIPE) rc = rc2; RTPollSetRemove(hPollSet, idPollSet); rc2 = RTPipeClose(*phPipeR); AssertRC(rc2); *phPipeR = NIL_RTPIPE; } return rc; } }
static void tstRTCreateProcEx2(const char *pszAsUser, const char *pszPassword) { RTTestISub("Standard Err"); RTPIPE hPipeR, hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS); const char * apszArgs[3] = { "non-existing-non-executable-file", "--testcase-child-2", NULL }; RTHANDLE Handle; Handle.enmType = RTHANDLETYPE_PIPE; Handle.u.hPipe = hPipeW; RTPROCESS hProc; RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL, NULL, &Handle, pszAsUser, pszPassword, &hProc), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); char szOutput[_4K]; size_t offOutput = 0; for (;;) { size_t cbLeft = sizeof(szOutput) - 1 - offOutput; RTTESTI_CHECK(cbLeft > 0); if (cbLeft == 0) break; size_t cbRead; int rc = RTPipeReadBlocking(hPipeR, &szOutput[offOutput], cbLeft, &cbRead); if (RT_FAILURE(rc)) { RTTESTI_CHECK_RC(rc, VERR_BROKEN_PIPE); break; } offOutput += cbRead; } szOutput[offOutput] = '\0'; RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND }; RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); RTThreadSleep(10); if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0) RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus); else if ( offOutput != sizeof("howdy") - 1 || strcmp(szOutput, "howdy")) RTTestIFailed("wrong output: \"%s\" (len=%u)", szOutput, offOutput); else RTTestIPassed(NULL); }
/** * If any Usbfs-related resources are currently allocated, then free them * and mark them as freed. */ void USBProxyBackendLinux::doUsbfsCleanupAsNeeded() { /* * Free resources. */ RTFileClose(mhFile); mhFile = NIL_RTFILE; RTPipeClose(mhWakeupPipeR); RTPipeClose(mhWakeupPipeW); mhWakeupPipeW = mhWakeupPipeR = NIL_RTPIPE; }
/** * Initializes the object (called right after construction). * * @returns S_OK on success and non-fatal failures, some COM error otherwise. */ int USBProxyBackendUsbIp::init(void) { int rc = VINF_SUCCESS; m = new Data; /** @todo: Pass in some config like host and port to connect to. */ /* Setup wakeup pipe and poll set first. */ rc = RTSemFastMutexCreate(&m->hMtxDevices); if (RT_SUCCESS(rc)) { rc = RTPipeCreate(&m->hWakeupPipeR, &m->hWakeupPipeW, 0); if (RT_SUCCESS(rc)) { rc = RTPollSetCreate(&m->hPollSet); if (RT_SUCCESS(rc)) { rc = RTPollSetAddPipe(m->hPollSet, m->hWakeupPipeR, RTPOLL_EVT_READ, USBIP_POLL_ID_PIPE); if (RT_SUCCESS(rc)) { /* Connect to the USB/IP host. */ rc = reconnect(); if (RT_SUCCESS(rc)) rc = start(); /* Start service thread. */ } if (RT_FAILURE(rc)) { RTPollSetRemove(m->hPollSet, USBIP_POLL_ID_PIPE); int rc2 = RTPollSetDestroy(m->hPollSet); AssertRC(rc2); } } if (RT_FAILURE(rc)) { int rc2 = RTPipeClose(m->hWakeupPipeR); AssertRC(rc2); rc2 = RTPipeClose(m->hWakeupPipeW); AssertRC(rc2); } } if (RT_FAILURE(rc)) RTSemFastMutexDestroy(m->hMtxDevices); } return rc; }
/** * Initialization routine for the usbfs based operation. * * @returns iprt status code. */ int USBProxyBackendLinux::initUsbfs(void) { Assert(mUsingUsbfsDevices); /* * Open the devices file. */ int rc; char *pszDevices = RTPathJoinA(mDevicesRoot.c_str(), "devices"); if (pszDevices) { rc = RTFileOpen(&mhFile, pszDevices, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); if (RT_SUCCESS(rc)) { rc = RTPipeCreate(&mhWakeupPipeR, &mhWakeupPipeW, 0 /*fFlags*/); if (RT_SUCCESS(rc)) { /* * Start the poller thread. */ rc = start(); if (RT_SUCCESS(rc)) { RTStrFree(pszDevices); LogFlowThisFunc(("returns successfully\n")); return VINF_SUCCESS; } RTPipeClose(mhWakeupPipeR); RTPipeClose(mhWakeupPipeW); mhWakeupPipeW = mhWakeupPipeR = NIL_RTPIPE; } else Log(("USBProxyBackendLinux::USBProxyBackendLinux: RTFilePipe failed with rc=%Rrc\n", rc)); RTFileClose(mhFile); } RTStrFree(pszDevices); } else { rc = VERR_NO_MEMORY; Log(("USBProxyBackendLinux::USBProxyBackendLinux: out of memory!\n")); } LogFlowThisFunc(("returns failure!!! (rc=%Rrc)\n", rc)); return rc; }
static RTEXITCODE tstRTPipe4Child(const char *pszPipe) { int rc = RTR3InitExeNoArguments(0); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); int64_t iNative; rc = RTStrToInt64Full(pszPipe, 10, &iNative); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTStrToUInt64Full(%s) -> %Rrc\n", pszPipe, rc); RTPIPE hPipe; rc = RTPipeFromNative(&hPipe, (RTHCINTPTR)iNative, RTPIPE_N_WRITE); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPipeFromNative(,%s,WRITE) -> %Rrc\n", pszPipe, rc); rc = RTPipeWriteBlocking(hPipe, g_szTest4Message, sizeof(g_szTest4Message) - 1, NULL); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPipeWriteBlocking() -> %Rrc\n", rc); rc = RTPipeClose(hPipe); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPipeClose() -> %Rrc\n", rc); return RTEXITCODE_SUCCESS; }
RTDECL(int) RTHandleClose(PRTHANDLE ph) { int rc = VINF_SUCCESS; if (ph) { switch (ph->enmType) { case RTHANDLETYPE_FILE: rc = RTFileClose(ph->u.hFile); ph->u.hFile = NIL_RTFILE; break; case RTHANDLETYPE_PIPE: rc = RTPipeClose(ph->u.hPipe); ph->u.hPipe = NIL_RTPIPE; break; case RTHANDLETYPE_SOCKET: AssertMsgFailed(("Socket not supported\n")); rc = VERR_NOT_SUPPORTED; break; case RTHANDLETYPE_THREAD: AssertMsgFailed(("Thread not supported\n")); rc = VERR_NOT_SUPPORTED; break; default: AssertMsgFailed(("Invalid type %d\n", ph->enmType)); rc = VERR_INVALID_PARAMETER; break; } } return rc; }
static void tstRTPipe4(void) { RTTestISub("Inherit non-standard pipe handle, write end"); char szPathSelf[RTPATH_MAX]; RTTESTI_CHECK_RETV(RTProcGetExecutablePath(szPathSelf, sizeof(szPathSelf)) == szPathSelf); RTPIPE hPipeR; RTPIPE hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS); RTHCINTPTR hNative = RTPipeToNative(hPipeW); RTTESTI_CHECK_RETV(hNative != -1); char szNative[64]; RTStrPrintf(szNative, sizeof(szNative), "%RHi", hNative); const char *papszArgs[4] = { szPathSelf, "--child-4", szNative, NULL }; RTPROCESS hChild; RTTESTI_CHECK_RC_RETV(RTProcCreate(szPathSelf, papszArgs, RTENV_DEFAULT, 0 /*fFlags*/, &hChild), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); char szTmp[1024]; size_t cbRead = 0; int rc; RTTESTI_CHECK_RC(rc = RTPipeReadBlocking(hPipeR, szTmp, sizeof(szTmp) - 1, &cbRead), VINF_SUCCESS); if (RT_FAILURE(rc)) cbRead = 0; RTTESTI_CHECK_RETV(cbRead < sizeof(szTmp)); szTmp[cbRead] = '\0'; size_t cbRead2; char szTmp2[4]; RTTESTI_CHECK_RC(RTPipeReadBlocking(hPipeR, szTmp2, sizeof(szTmp2), &cbRead2), VERR_BROKEN_PIPE); RTTESTI_CHECK_RC(rc = RTPipeClose(hPipeR), VINF_SUCCESS); if (RT_FAILURE(rc)) RTTESTI_CHECK_RC(RTProcTerminate(hChild), VINF_SUCCESS); RTPROCSTATUS ProcStatus; RTTESTI_CHECK_RC(rc = RTProcWait(hChild, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); if (RT_FAILURE(rc)) return; RTTESTI_CHECK( ProcStatus.enmReason == RTPROCEXITREASON_NORMAL && ProcStatus.iStatus == 0); if (memcmp(szTmp, g_szTest4Message, sizeof(g_szTest4Message))) RTTestIFailed("Message mismatch.\n:Expected '%s'\nGot '%s'\n", g_szTest4Message, szTmp); }
static void tstRTPipe3(void) { RTTestISub("Full write buffer"); RTPIPE hPipeR = (RTPIPE)999999; RTPIPE hPipeW = (RTPIPE)999999; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); static char s_abBuf[_256K]; int rc = VINF_SUCCESS; size_t cbTotal = 0; memset(s_abBuf, 0xff, sizeof(s_abBuf)); for (;;) { RTTESTI_CHECK(cbTotal < _1G); if (cbTotal > _1G) break; size_t cbWritten = _1G; rc = RTPipeWrite(hPipeW, s_abBuf, sizeof(s_abBuf), &cbWritten); RTTESTI_CHECK_MSG(rc == VINF_SUCCESS || rc == VINF_TRY_AGAIN, ("rc=%Rrc\n", rc)); if (rc != VINF_SUCCESS) break; cbTotal += cbWritten; } if (rc == VINF_TRY_AGAIN) { RTTestIPrintf(RTTESTLVL_ALWAYS, "cbTotal=%zu (%#zx)\n", cbTotal, cbTotal); RTTESTI_CHECK_RC(RTPipeSelectOne(hPipeW, 0), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPipeSelectOne(hPipeW, 1), VERR_TIMEOUT); size_t cbRead; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, s_abBuf, RT_MIN(sizeof(s_abBuf), cbTotal) / 2, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeSelectOne(hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeSelectOne(hPipeW, 1), VINF_SUCCESS); size_t cbWritten = _1G; rc = RTPipeWrite(hPipeW, s_abBuf, sizeof(s_abBuf), &cbWritten); RTTESTI_CHECK(rc == VINF_SUCCESS); } RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); }
/** * Closes the proxy device. */ static DECLCALLBACK(void) usbProxyFreeBSDClose(PUSBPROXYDEV pProxyDev) { PUSBPROXYDEVFBSD pDevFBSD = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVFBSD); LogFlow(("usbProxyFreeBSDClose: pProxyDev=%s\n", pProxyDev->pUsbIns->pszName)); /* sanity check */ AssertPtrReturnVoid(pDevFBSD); usbProxyFreeBSDFsUnInit(pProxyDev); RTPipeClose(pDevFBSD->hPipeWakeupR); RTPipeClose(pDevFBSD->hPipeWakeupW); RTFileClose(pDevFBSD->hFile); pDevFBSD->hFile = NIL_RTFILE; LogFlow(("usbProxyFreeBSDClose: returns\n")); }
/** * Close the USB device. * * @param pProxyDev The device instance. */ static DECLCALLBACK(void) usbProxySolarisClose(PUSBPROXYDEV pProxyDev) { LogFlow((USBPROXY ":usbProxySolarisClose: pProxyDev=%p\n", pProxyDev)); PUSBPROXYDEVSOL pDevSol = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVSOL); /* Close the device (do not re-enumerate). */ VBOXUSBREQ_CLOSE_DEVICE CloseReq; CloseReq.ResetLevel = VBOXUSB_RESET_LEVEL_CLOSE; usbProxySolarisIOCtl(pDevSol, VBOXUSB_IOCTL_CLOSE_DEVICE, &CloseReq, sizeof(CloseReq)); pProxyDev->fDetached = true; usbProxySolarisCloseFile(pDevSol); /* * Now we can close it and free all the resources. */ RTCritSectDelete(&pDevSol->CritSect); PUSBPROXYURBSOL pUrbSol = NULL; while ((pUrbSol = pDevSol->pInFlightHead) != NULL) { pDevSol->pInFlightHead = pUrbSol->pNext; RTMemFree(pUrbSol); } while ((pUrbSol = pDevSol->pFreeHead) != NULL) { pDevSol->pFreeHead = pUrbSol->pNext; RTMemFree(pUrbSol); } RTPipeClose(pDevSol->hPipeWakeupR); RTPipeClose(pDevSol->hPipeWakeupW); RTStrFree(pDevSol->pszDevicePath); pDevSol->pszDevicePath = NULL; USBLibTerm(); }
static RTEXITCODE tstRTPipe5Child(const char *pszPipe) { int rc = RTR3InitExeNoArguments(0); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); int64_t iNative; rc = RTStrToInt64Full(pszPipe, 10, &iNative); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTStrToUInt64Full(%s) -> %Rrc\n", pszPipe, rc); RTPIPE hPipe; rc = RTPipeFromNative(&hPipe, (RTHCINTPTR)iNative, RTPIPE_N_READ); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPipeFromNative(,%s,READ) -> %Rrc\n", pszPipe, rc); /// char szTmp[1024]; size_t cbRead = 0; rc = RTPipeReadBlocking(hPipe, szTmp, sizeof(szTmp) - 1, &cbRead); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPipeReadBlocking() -> %Rrc\n", rc); szTmp[cbRead] = '\0'; size_t cbRead2; char szTmp2[4]; rc = RTPipeReadBlocking(hPipe, szTmp2, sizeof(szTmp2), &cbRead2); if (rc != VERR_BROKEN_PIPE) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPipeReadBlocking() -> %Rrc instead of VERR_BROKEN_PIPE\n", rc); rc = RTPipeClose(hPipe); if (RT_FAILURE(rc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPipeClose() -> %Rrc\n", rc); if (memcmp(szTmp, g_szTest5Message, sizeof(g_szTest5Message))) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Message mismatch.\n:Expected '%s'\nGot '%s'\n", g_szTest5Message, szTmp); return RTEXITCODE_SUCCESS; }
/** * Opens the USB device. * * @returns VBox status code. * @param pProxyDev The device instance. * @param pszAddress The unique device identifier. * The format of this string is "VendorId:ProducIt:Release:StaticPath". * @param pvBackend Backend specific pointer, unused for the solaris backend. */ static DECLCALLBACK(int) usbProxySolarisOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend) { PUSBPROXYDEVSOL pDevSol = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVSOL); LogFlowFunc((USBPROXY ":usbProxySolarisOpen pProxyDev=%p pszAddress=%s pvBackend=%p\n", pProxyDev, pszAddress, pvBackend)); /* * Initialize our USB R3 lib. */ int rc = USBLibInit(); if (RT_SUCCESS(rc)) { /* * Allocate and initialize the solaris backend data. */ AssertCompile(PATH_MAX >= MAXPATHLEN); char szDeviceIdent[PATH_MAX+48]; rc = RTStrPrintf(szDeviceIdent, sizeof(szDeviceIdent), "%s", pszAddress); if (RT_SUCCESS(rc)) { rc = RTCritSectInit(&pDevSol->CritSect); if (RT_SUCCESS(rc)) { /* * Create wakeup pipe. */ rc = RTPipeCreate(&pDevSol->hPipeWakeupR, &pDevSol->hPipeWakeupW, 0); if (RT_SUCCESS(rc)) { int Instance; char *pszDevicePath = NULL; rc = USBLibGetClientInfo(szDeviceIdent, &pszDevicePath, &Instance); if (RT_SUCCESS(rc)) { pDevSol->pszDevicePath = pszDevicePath; /* * Open the client driver. */ RTFILE hFile; rc = RTFileOpen(&hFile, pDevSol->pszDevicePath, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); if (RT_SUCCESS(rc)) { pDevSol->hFile = hFile; pDevSol->pProxyDev = pProxyDev; /* * Verify client driver version. */ VBOXUSBREQ_GET_VERSION GetVersionReq; bzero(&GetVersionReq, sizeof(GetVersionReq)); rc = usbProxySolarisIOCtl(pDevSol, VBOXUSB_IOCTL_GET_VERSION, &GetVersionReq, sizeof(GetVersionReq)); if (RT_SUCCESS(rc)) { if ( GetVersionReq.u32Major == VBOXUSB_VERSION_MAJOR && GetVersionReq.u32Minor >= VBOXUSB_VERSION_MINOR) { /* * Try & get the current cached config from Solaris. */ usbProxySolarisGetActiveConfig(pDevSol); return VINF_SUCCESS; } else { LogRel((USBPROXY ":version mismatch! driver v%d.%d expecting ~v%d.%d\n", GetVersionReq.u32Major, GetVersionReq.u32Minor, VBOXUSB_VERSION_MAJOR, VBOXUSB_VERSION_MINOR)); rc = VERR_VERSION_MISMATCH; } } else LogRel((USBPROXY ":failed to query driver version. rc=%Rrc\n", rc)); RTFileClose(pDevSol->hFile); pDevSol->hFile = NIL_RTFILE; pDevSol->pProxyDev = NULL; } else LogRel((USBPROXY ":failed to open device. rc=%Rrc pszDevicePath=%s\n", rc, pDevSol->pszDevicePath)); RTStrFree(pDevSol->pszDevicePath); pDevSol->pszDevicePath = NULL; } else { LogRel((USBPROXY ":failed to get client info. rc=%Rrc pszDevicePath=%s\n", rc, pDevSol->pszDevicePath)); if (rc == VERR_NOT_FOUND) rc = VERR_OPEN_FAILED; } RTPipeClose(pDevSol->hPipeWakeupR); RTPipeClose(pDevSol->hPipeWakeupW); } RTCritSectDelete(&pDevSol->CritSect); } else LogRel((USBPROXY ":RTCritSectInit failed. rc=%Rrc pszAddress=%s\n", rc, pszAddress)); } else LogRel((USBPROXY ":RTStrAPrintf failed. rc=%Rrc pszAddress=%s\n", rc, pszAddress)); } else LogRel((USBPROXY ":USBLibInit failed. rc=%Rrc\n", rc)); USBLibTerm(); return rc; }
/** * Runs a process, collecting the standard output and/or standard error. * * * @returns IPRT status code * @retval VERR_NO_TRANSLATION if the output of the program isn't valid UTF-8 * or contains a nul character. * @retval VERR_TOO_MUCH_DATA if the process produced too much data. * * @param pszExec Executable image to use to create the child process. * @param papszArgs Pointer to an array of arguments to the child. The * array terminated by an entry containing NULL. * @param hEnv Handle to the environment block for the child. * @param fFlags A combination of RTPROCEXEC_FLAGS_XXX. The @a * ppszStdOut and @a ppszStdErr parameters takes precedence * over redirection flags. * @param pStatus Where to return the status on success. * @param ppszStdOut Where to return the text written to standard output. If * NULL then standard output will not be collected and go * to the standard output handle of the process. * Free with RTStrFree, regardless of return status. * @param ppszStdErr Where to return the text written to standard error. If * NULL then standard output will not be collected and go * to the standard error handle of the process. * Free with RTStrFree, regardless of return status. */ int RTProcExecToString(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags, PRTPROCSTATUS pStatus, char **ppszStdOut, char **ppszStdErr) { int rc2; /* * Clear output arguments (no returning failure here, simply crash!). */ AssertPtr(pStatus); pStatus->enmReason = RTPROCEXITREASON_ABEND; pStatus->iStatus = RTEXITCODE_FAILURE; AssertPtrNull(ppszStdOut); if (ppszStdOut) *ppszStdOut = NULL; AssertPtrNull(ppszStdOut); if (ppszStdErr) *ppszStdErr = NULL; /* * Check input arguments. */ AssertReturn(!(fFlags & ~RTPROCEXEC_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER); /* * Do we need a standard input bitbucket? */ int rc = VINF_SUCCESS; PRTHANDLE phChildStdIn = NULL; RTHANDLE hChildStdIn; hChildStdIn.enmType = RTHANDLETYPE_FILE; hChildStdIn.u.hFile = NIL_RTFILE; if ((fFlags & RTPROCEXEC_FLAGS_STDIN_NULL) && RT_SUCCESS(rc)) { phChildStdIn = &hChildStdIn; rc = RTFileOpenBitBucket(&hChildStdIn.u.hFile, RTFILE_O_READ); } /* * Create the output pipes / bitbuckets. */ RTPIPE hPipeStdOutR = NIL_RTPIPE; PRTHANDLE phChildStdOut = NULL; RTHANDLE hChildStdOut; hChildStdOut.enmType = RTHANDLETYPE_PIPE; hChildStdOut.u.hPipe = NIL_RTPIPE; if (ppszStdOut && RT_SUCCESS(rc)) { phChildStdOut = &hChildStdOut; rc = RTPipeCreate(&hPipeStdOutR, &hChildStdOut.u.hPipe, 0 /*fFlags*/); } else if ((fFlags & RTPROCEXEC_FLAGS_STDOUT_NULL) && RT_SUCCESS(rc)) { phChildStdOut = &hChildStdOut; hChildStdOut.enmType = RTHANDLETYPE_FILE; hChildStdOut.u.hFile = NIL_RTFILE; rc = RTFileOpenBitBucket(&hChildStdOut.u.hFile, RTFILE_O_WRITE); } RTPIPE hPipeStdErrR = NIL_RTPIPE; PRTHANDLE phChildStdErr = NULL; RTHANDLE hChildStdErr; hChildStdErr.enmType = RTHANDLETYPE_PIPE; hChildStdErr.u.hPipe = NIL_RTPIPE; if (ppszStdErr && RT_SUCCESS(rc)) { phChildStdErr = &hChildStdErr; rc = RTPipeCreate(&hPipeStdErrR, &hChildStdErr.u.hPipe, 0 /*fFlags*/); } else if ((fFlags & RTPROCEXEC_FLAGS_STDERR_NULL) && RT_SUCCESS(rc)) { phChildStdErr = &hChildStdErr; hChildStdErr.enmType = RTHANDLETYPE_FILE; hChildStdErr.u.hFile = NIL_RTFILE; rc = RTFileOpenBitBucket(&hChildStdErr.u.hFile, RTFILE_O_WRITE); } if (RT_SUCCESS(rc)) { RTPOLLSET hPollSet; rc = RTPollSetCreate(&hPollSet); if (RT_SUCCESS(rc)) { if (hPipeStdOutR != NIL_RTPIPE && RT_SUCCESS(rc)) rc = RTPollSetAddPipe(hPollSet, hPipeStdOutR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, 1); if (hPipeStdErrR != NIL_RTPIPE) rc = RTPollSetAddPipe(hPollSet, hPipeStdErrR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, 2); } if (RT_SUCCESS(rc)) { /* * Create the process. */ RTPROCESS hProc; rc = RTProcCreateEx(g_szSvnPath, papszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL /*phStdIn*/, phChildStdOut, phChildStdErr, NULL /*pszAsUser*/, NULL /*pszPassword*/, &hProc); rc2 = RTHandleClose(&hChildStdErr); AssertRC(rc2); rc2 = RTHandleClose(&hChildStdOut); AssertRC(rc2); if (RT_SUCCESS(rc)) { /* * Process output and wait for the process to finish. */ size_t cbStdOut = 0; size_t offStdOut = 0; size_t cbStdErr = 0; size_t offStdErr = 0; for (;;) { if (hPipeStdOutR != NIL_RTPIPE) rc = rtProcProcessOutput(rc, &hPipeStdOutR, &cbStdOut, &offStdOut, ppszStdOut, hPollSet, 1); if (hPipeStdErrR != NIL_RTPIPE) rc = rtProcProcessOutput(rc, &hPipeStdErrR, &cbStdErr, &offStdErr, ppszStdErr, hPollSet, 2); if (hPipeStdOutR == NIL_RTPIPE && hPipeStdErrR == NIL_RTPIPE) break; if (hProc != NIL_RTPROCESS) { rc2 = RTProcWait(hProc, RTPROCWAIT_FLAGS_NOBLOCK, pStatus); if (rc2 != VERR_PROCESS_RUNNING) { if (RT_FAILURE(rc2)) rc = rc2; hProc = NIL_RTPROCESS; } } rc2 = RTPoll(hPollSet, 10000, NULL, NULL); Assert(RT_SUCCESS(rc2) || rc2 == VERR_TIMEOUT); } if (RT_SUCCESS(rc)) { if ( (ppszStdOut && *ppszStdOut && !RTStrIsValidEncoding(*ppszStdOut)) || (ppszStdErr && *ppszStdErr && !RTStrIsValidEncoding(*ppszStdErr)) ) rc = VERR_NO_TRANSLATION; } /* * No more output, just wait for it to finish. */ if (hProc != NIL_RTPROCESS) { rc2 = RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, pStatus); if (RT_FAILURE(rc2)) rc = rc2; } } RTPollSetDestroy(hPollSet); } } rc2 = RTHandleClose(&hChildStdErr); AssertRC(rc2); rc2 = RTHandleClose(&hChildStdOut); AssertRC(rc2); rc2 = RTHandleClose(&hChildStdIn); AssertRC(rc2); rc2 = RTPipeClose(hPipeStdErrR); AssertRC(rc2); rc2 = RTPipeClose(hPipeStdOutR); AssertRC(rc2); return rc; }
static void tstRTPipe1(void) { RTTestISub("Basics"); RTPIPE hPipeR = NIL_RTPIPE; RTPIPE hPipeW = NIL_RTPIPE; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RETV(hPipeR != NIL_RTPIPE); RTTESTI_CHECK_RETV(hPipeW != NIL_RTPIPE); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(NIL_RTPIPE), VINF_SUCCESS); hPipeR = NIL_RTPIPE; hPipeW = NIL_RTPIPE; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_READ | RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS); int rc = RTPipeFlush(hPipeW); RTTESTI_CHECK_MSG(rc == VERR_NOT_SUPPORTED || rc == VINF_SUCCESS, ("%Rrc\n", rc)); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_READ), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 0), VERR_TIMEOUT); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 1), VERR_TIMEOUT); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeW, 1), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_READ), VINF_SUCCESS); size_t cbRead = ~(size_t)0; char abBuf[_64K + _4K]; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, sizeof(abBuf), &cbRead), VINF_TRY_AGAIN); RTTESTI_CHECK_RETV(cbRead == 0); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, 1, &cbRead), VINF_TRY_AGAIN); RTTESTI_CHECK_RETV(cbRead == 0); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 0); size_t cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, abBuf, 0, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbWritten == 0); /* We can write a number of bytes without blocking (see PIPE_BUF on POSIX systems). */ cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "42", 2, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_MSG_RETV(cbWritten == 2, ("cbWritten=%zu\n", cbWritten)); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "!", 1, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbWritten == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, 3, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 3); RTTESTI_CHECK_RETV(!memcmp(abBuf, "42!", 3)); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "BigQ", 4, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbWritten == 4); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 1), VINF_SUCCESS); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, sizeof(abBuf), &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 4); RTTESTI_CHECK_RETV(!memcmp(abBuf, "BigQ", 4)); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "H2G2", 4, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbWritten == 4); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[0], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten - 1, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[1], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten - 2, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[2], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten - 3, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[3], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 1); RTTESTI_CHECK_RETV(!memcmp(abBuf, "H2G2", 4)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten - 4, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTestISub("VERR_BROKEN_PIPE"); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC(RTPipeWrite(hPipeW, "", 0, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 0); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC(RTPipeWrite(hPipeW, "4", 1, &cbWritten), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbWritten == ~(size_t)2); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); cbRead = ~(size_t)0; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, abBuf, 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 0); cbRead = ~(size_t)3; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, abBuf, sizeof(abBuf), &cbRead), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbRead == ~(size_t)3); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC(RTPipeWrite(hPipeW, "42", 2, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 2); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 0); cbRead = ~(size_t)0; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, &abBuf[0], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, &abBuf[1], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 1); RTTESTI_CHECK(!memcmp(abBuf, "42", 2)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, abBuf, 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 0); cbRead = ~(size_t)3; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, sizeof(abBuf), &cbRead), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbRead == ~(size_t)3); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTestISub("Blocking"); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "42!", 3, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 3); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, abBuf, 3, NULL), VINF_SUCCESS); RTTESTI_CHECK(!memcmp(abBuf, "42!", 3)); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[0], 0, NULL), VINF_SUCCESS); cbRead = ~(size_t)42; RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[0], 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 0); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[0], 1, NULL), VERR_BROKEN_PIPE); cbRead = ~(size_t)42; RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[0], 1, &cbRead), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbRead == 0); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "42!", 3, NULL), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 3); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[0], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 1); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[1], 1, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[2], 1, NULL), VINF_SUCCESS); RTTESTI_CHECK(!memcmp(abBuf, "42!", 3)); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "", 0, NULL), VINF_SUCCESS); cbWritten = ~(size_t)9; RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "", 0, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 0); RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "42", 2, NULL), VERR_BROKEN_PIPE); cbWritten = ~(size_t)9; RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "42", 2, &cbWritten), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbWritten == 0); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); }
/** * Destruct a TCP socket stream driver instance. * * Most VM resources are freed by the VM. This callback is provided so that * any non-VM resources can be freed correctly. * * @param pDrvIns The driver instance data. */ static DECLCALLBACK(void) drvTCPDestruct(PPDMDRVINS pDrvIns) { PDRVTCP pThis = PDMINS_2_DATA(pDrvIns, PDRVTCP); LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation)); PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns); drvTCPShutdownListener(pThis); /* * While the thread exits, clean up as much as we can. */ if (pThis->hTcpSock != NIL_RTSOCKET) { int rc = RTPollSetRemove(pThis->hPollSet, DRVTCP_POLLSET_ID_SOCKET); AssertRC(rc); rc = RTSocketShutdown(pThis->hTcpSock, true /* fRead */, true /* fWrite */); AssertRC(rc); rc = RTSocketClose(pThis->hTcpSock); AssertRC(rc); RT_NOREF(rc); pThis->hTcpSock = NIL_RTSOCKET; } if (pThis->hPipeWakeR != NIL_RTPIPE) { int rc = RTPipeClose(pThis->hPipeWakeR); AssertRC(rc); pThis->hPipeWakeR = NIL_RTPIPE; } if (pThis->hPipeWakeW != NIL_RTPIPE) { int rc = RTPipeClose(pThis->hPipeWakeW); AssertRC(rc); pThis->hPipeWakeW = NIL_RTPIPE; } if (pThis->hPollSet != NIL_RTPOLLSET) { int rc = RTPollSetDestroy(pThis->hPollSet); AssertRC(rc); pThis->hPollSet = NIL_RTPOLLSET; } MMR3HeapFree(pThis->pszLocation); pThis->pszLocation = NULL; /* * Wait for the thread. */ if (pThis->ListenThread != NIL_RTTHREAD) { int rc = RTThreadWait(pThis->ListenThread, 30000, NULL); if (RT_SUCCESS(rc)) pThis->ListenThread = NIL_RTTHREAD; else LogRel(("DrvTCP%d: listen thread did not terminate (%Rrc)\n", pDrvIns->iInstance, rc)); } }
static void tstRTPoll1(void) { RTTestISub("Basics"); /* create and destroy. */ RTPOLLSET hSet = NIL_RTPOLLSET; RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RETV(hSet != NIL_RTPOLLSET); RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetDestroy(NIL_RTPOLLSET), VINF_SUCCESS); /* empty set, adding a NIL handle. */ hSet = NIL_RTPOLLSET; RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RETV(hSet != NIL_RTPOLLSET); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 0); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 0, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, NIL_RTPIPE, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 0); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 0), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 0); RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS); /* * Set with pipes */ RTPIPE hPipeR; RTPIPE hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0/*fFlags*/), VINF_SUCCESS); hSet = NIL_RTPOLLSET; RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RETV(hSet != NIL_RTPOLLSET); /* add the read pipe */ RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VINF_SUCCESS); RTHANDLE Handle; RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 1 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeR); /* poll on the set, should time out. */ RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPoll(hSet, 1, NULL, NULL), VERR_TIMEOUT); /* add the write pipe with error detection only, check that poll still times out. remove it again. */ RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, hPipeW, RTPOLL_EVT_ERROR, 11 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 2); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 11 /*id*/, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPoll(hSet, 1, NULL, NULL), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 11), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1); /* add the write pipe */ RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, hPipeW, RTPOLL_EVT_WRITE, 10 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 2); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 10 /*id*/, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeW); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 1 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeR); /* poll on the set again, now it should indicate hPipeW is ready. */ int rc; RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(rc = RTPoll(hSet, 100, NULL, NULL), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK_RC(RTPoll(hSet, RT_INDEFINITE_WAIT, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 0, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 100, NULL, NULL), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, RT_INDEFINITE_WAIT, NULL, NULL), VINF_SUCCESS); uint32_t fEvents = UINT32_MAX; uint32_t id = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPoll(hSet, 250, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, RT_INDEFINITE_WAIT, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); } fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 100, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, RT_INDEFINITE_WAIT, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); } /* Write to the pipe. Currently ASSUMING we'll get the read ready now... Good idea? */ RTTESTI_CHECK_RC(rc = RTPipeWriteBlocking(hPipeW, "hello", 5, NULL), VINF_SUCCESS); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPoll(hSet, 256, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, RT_INDEFINITE_WAIT, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); } fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 383, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, RT_INDEFINITE_WAIT, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); } } /* Remove the read pipe, do a quick poll check. */ RTTESTI_CHECK_RC_RETV(RTPollSetRemove(hSet, 1), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeW); RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VINF_SUCCESS); /* Add it back and check that we now get the write handle when polling. (Is this FIFOing a good idea?) */ RTTESTI_CHECK_RC_RETV(RTPoll(hSet, 0, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 2); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 1 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeR); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeW); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 555, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); /* Remove it again and break the pipe by closing the read end. */ RTTESTI_CHECK_RC_RETV(RTPollSetRemove(hSet, 1), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeW); RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK_MSG( fEvents == RTPOLL_EVT_ERROR \ || fEvents == (RTPOLL_EVT_ERROR | RTPOLL_EVT_WRITE), ("%#x\n", fEvents)); RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); /* * Check FIFO order when removing and adding. * * Note! FIFO order is not guaranteed when a handle has more than one entry * in the set. */ RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0/*fFlags*/), VINF_SUCCESS); RTPIPE hPipeR2, hPipeW2; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR2, &hPipeW2, 0/*fFlags*/), VINF_SUCCESS); RTPIPE hPipeR3, hPipeW3; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR3, &hPipeW3, 0/*fFlags*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeW, RTPOLL_EVT_WRITE, 2 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR2, RTPOLL_EVT_READ, 3 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeW2, RTPOLL_EVT_WRITE, 4 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR3, RTPOLL_EVT_READ, 5 /*id*/), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 2); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeW, "hello", 5, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeW2, "hello", 5, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeW3, "hello", 5, NULL), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 1), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 2); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 2), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 3); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 3), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 4); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 4), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 5); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 5), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW2), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeR2), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW3), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeR3), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS); }
static void tstRTPoll2(void) { RTTestISub("Negative"); /* * Bad set pointer and handle values. */ RTTESTI_CHECK_RC(RTPollSetCreate(NULL), VERR_INVALID_POINTER); RTPOLLSET hSetInvl = (RTPOLLSET)(intptr_t)-3; RTTESTI_CHECK_RC(RTPollSetDestroy(hSetInvl), VERR_INVALID_HANDLE); RTHANDLE Handle; Handle.enmType = RTHANDLETYPE_PIPE; Handle.u.hPipe = NIL_RTPIPE; RTTESTI_CHECK_RC(RTPollSetAdd(hSetInvl, &Handle, RTPOLL_EVT_ERROR, 1), VERR_INVALID_HANDLE); RTTESTI_CHECK_RC(RTPollSetRemove(hSetInvl, 1), VERR_INVALID_HANDLE); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSetInvl, 1, NULL), VERR_INVALID_HANDLE); RTTESTI_CHECK(RTPollSetGetCount(hSetInvl) == UINT32_MAX); RTTESTI_CHECK_RC(RTPoll(hSetInvl, 0, NULL, NULL), VERR_INVALID_HANDLE); RTTESTI_CHECK_RC(RTPollNoResume(hSetInvl, 0, NULL, NULL), VERR_INVALID_HANDLE); /* * Invalid arguments and other stuff. */ RTPOLLSET hSet = NIL_RTPOLLSET; RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPoll(hSet, RT_INDEFINITE_WAIT, NULL, NULL), VERR_DEADLOCK); RTTESTI_CHECK_RC(RTPollNoResume(hSet, RT_INDEFINITE_WAIT, NULL, NULL), VERR_DEADLOCK); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, UINT32_MAX), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 1), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC(RTPollSetAdd(hSet, NULL, RTPOLL_EVT_ERROR, 1), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetAdd(hSet, &Handle, RTPOLL_EVT_ERROR, UINT32_MAX), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTPollSetAdd(hSet, &Handle, UINT32_MAX, 3), VERR_INVALID_PARAMETER); Handle.enmType = RTHANDLETYPE_INVALID; RTTESTI_CHECK_RC(RTPollSetAdd(hSet, &Handle, RTPOLL_EVT_ERROR, 3), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTPollSetAdd(hSet, NULL, RTPOLL_EVT_ERROR, UINT32_MAX), VERR_INVALID_PARAMETER); /* duplicate id */ RTPIPE hPipeR; RTPIPE hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0/*fFlags*/), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_ERROR, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_ERROR, 0), VERR_POLL_HANDLE_ID_EXISTS); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 0), VINF_SUCCESS); RTPipeClose(hPipeR); RTPipeClose(hPipeW); /* non-pollable handle */ RTFILE hBitBucket; RTTESTI_CHECK_RC_RETV(RTFileOpenBitBucket(&hBitBucket, RTFILE_O_WRITE), VINF_SUCCESS); Handle.enmType = RTHANDLETYPE_FILE; Handle.u.hFile = hBitBucket; RTTESTI_CHECK_RC(RTPollSetAdd(hSet, &Handle, RTPOLL_EVT_WRITE, 10), VERR_POLL_HANDLE_NOT_POLLABLE); RTFileClose(hBitBucket); RTTESTI_CHECK_RC_RETV(RTPollSetDestroy(hSet), VINF_SUCCESS); }