Changeset 27933 in vbox for trunk/src/VBox/Devices/Serial/DrvNamedPipe.cpp
- Timestamp:
- Apr 1, 2010 12:41:47 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 59633
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Serial/DrvNamedPipe.cpp
r27497 r27933 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox stream drivers: Named pipe stream3 * Named pipe / local socket stream driver. 4 4 */ 5 5 … … 76 76 bool fIsServer; 77 77 #ifdef RT_OS_WINDOWS 78 /* File handle of the named pipe. */78 /** File handle of the named pipe. */ 79 79 HANDLE NamedPipe; 80 /* Overlapped structure for writes. */80 /** Overlapped structure for writes. */ 81 81 OVERLAPPED OverlappedWrite; 82 /* Overlapped structure for reads. */82 /** Overlapped structure for reads. */ 83 83 OVERLAPPED OverlappedRead; 84 /* Listen thread wakeup semaphore */85 RTSEMEVENT 84 /** Listen thread wakeup semaphore */ 85 RTSEMEVENTMULTI ListenSem; 86 86 #else /* !RT_OS_WINDOWS */ 87 87 /** Socket handle of the local socket for server. */ … … 93 93 RTTHREAD ListenThread; 94 94 /** Flag to signal listening thread to shut down. */ 95 bool 95 bool volatile fShutdown; 96 96 } DRVNAMEDPIPE, *PDRVNAMEDPIPE; 97 97 … … 153 153 ) 154 154 ) 155 156 155 { 157 156 FlushFileBuffers(pThis->NamedPipe); … … 238 237 if (RT_FAILURE(rc)) 239 238 { 239 /** @todo WriteFile(pipe) has been observed to return ERROR_NO_DATA 240 * (VERR_NO_DATA) instead of ERROR_BROKEN_PIPE, when the pipe is 241 * disconnected. */ 240 242 if ( rc == VERR_EOF 241 243 || rc == VERR_BROKEN_PIPE) … … 340 342 if (hrc == ERROR_PIPE_CONNECTED) 341 343 { 342 RTSemEvent Wait(pThis->ListenSem, 250);344 RTSemEventMultiWait(pThis->ListenSem, 250); 343 345 } 344 346 else if (hrc != ERROR_SUCCESS) … … 363 365 break; 364 366 } 367 if (pThis->LocalSocket != -1) 368 { 369 LogRel(("NamedPipe%d: only single connection supported\n", pThis->pDrvIns->iInstance)); 370 close(s); 371 } 365 372 else 366 { 367 if (pThis->LocalSocket != -1) 368 { 369 LogRel(("NamedPipe%d: only single connection supported\n", pThis->pDrvIns->iInstance)); 370 close(s); 371 } 372 else 373 pThis->LocalSocket = s; 374 } 373 pThis->LocalSocket = s; 374 375 375 #endif /* !RT_OS_WINDOWS */ 376 376 } … … 379 379 CloseHandle(hEvent); 380 380 #endif 381 pThis->ListenThread = NIL_RTTHREAD;382 381 return VINF_SUCCESS; 383 382 } … … 386 385 387 386 /** 387 * Common worker for drvNamedPipePowerOff and drvNamedPipeDestructor. 388 * 389 * @param pThis The instance data. 390 */ 391 static void drvNamedPipeShutdownListener(PDRVNAMEDPIPE pThis) 392 { 393 /* 394 * Signal shutdown of the listener thread. 395 */ 396 pThis->fShutdown = true; 397 #ifdef RT_OS_WINDOWS 398 if ( pThis->fIsServer 399 && pThis->NamedPipe != INVALID_HANDLE_VALUE) 400 { 401 FlushFileBuffers(pThis->NamedPipe); 402 DisconnectNamedPipe(pThis->NamedPipe); 403 404 BOOL fRc = CloseHandle(pThis->NamedPipe); 405 Assert(fRc); NOREF(fRc); 406 pThis->NamedPipe = INVALID_HANDLE_VALUE; 407 408 /* Wake up listen thread */ 409 if (pThis->ListenSem != NIL_RTSEMEVENT) 410 RTSemEventMultiSignal(pThis->ListenSem); 411 } 412 #else 413 if ( pThis->fIsServer 414 && pThis->LocalSocketServer != -1) 415 { 416 int rc = shutdown(pThis->LocalSocketServer, SHUT_RDWR); 417 AssertRC(rc == 0); NOREF(rc); 418 419 rc = close(pThis->LocalSocketServer); 420 AssertRC(rc == 0); 421 pThis->LocalSocketServer = -1; 422 } 423 #endif 424 } 425 426 427 /** 388 428 * Power off a named pipe stream driver instance. 389 429 * … … 397 437 LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation)); 398 438 399 pThis->fShutdown = true; 400 401 #ifdef RT_OS_WINDOWS 402 if (pThis->NamedPipe != INVALID_HANDLE_VALUE) 403 { 404 if (pThis->fIsServer) 405 { 406 FlushFileBuffers(pThis->NamedPipe); 407 DisconnectNamedPipe(pThis->NamedPipe); 408 } 409 410 CloseHandle(pThis->NamedPipe); 411 pThis->NamedPipe = INVALID_HANDLE_VALUE; 412 CloseHandle(pThis->OverlappedRead.hEvent); 413 CloseHandle(pThis->OverlappedWrite.hEvent); 414 } 415 if (pThis->fIsServer) 416 { 417 /* Wake up listen thread */ 418 RTSemEventSignal(pThis->ListenSem); 419 RTSemEventDestroy(pThis->ListenSem); 420 } 421 #else /* !RT_OS_WINDOWS */ 422 if (pThis->fIsServer) 423 { 424 if (pThis->LocalSocketServer != -1) 425 { 426 close(pThis->LocalSocketServer); 427 pThis->LocalSocketServer = -1; 428 } 429 if (pThis->pszLocation) 430 RTFileDelete(pThis->pszLocation); 431 } 432 else 433 { 434 if (pThis->LocalSocket != -1) 435 { 436 close(pThis->LocalSocket); 437 pThis->LocalSocket = -1; 438 } 439 } 440 #endif /* !RT_OS_WINDOWS */ 439 drvNamedPipeShutdownListener(pThis); 441 440 } 442 441 … … 456 455 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns); 457 456 458 if (pThis->ListenThread) 459 { RTThreadWait(pThis->ListenThread, 250, NULL); 460 if (pThis->ListenThread != NIL_RTTHREAD) 461 LogRel(("NamedPipe%d: listen thread did not terminate\n", pDrvIns->iInstance)); 462 } 463 464 if (pThis->pszLocation) 465 MMR3HeapFree(pThis->pszLocation); 457 drvNamedPipeShutdownListener(pThis); 458 459 /* 460 * While the thread exits, clean up as much as we can. 461 */ 462 #ifdef RT_OS_WINDOWS 463 if (pThis->NamedPipe != INVALID_HANDLE_VALUE) 464 { 465 CloseHandle(pThis->NamedPipe); 466 pThis->NamedPipe = INVALID_HANDLE_VALUE; 467 } 468 if (pThis->OverlappedRead.hEvent != NULL) 469 { 470 CloseHandle(pThis->OverlappedRead.hEvent); 471 pThis->OverlappedRead.hEvent = NULL; 472 } 473 if (pThis->OverlappedWrite.hEvent != NULL) 474 { 475 CloseHandle(pThis->OverlappedWrite.hEvent); 476 pThis->OverlappedWrite.hEvent = NULL; 477 } 478 #else /* !RT_OS_WINDOWS */ 479 Assert(pThis->LocalSocketServer == -1); 480 if (pThis->LocalSocket != -1) 481 { 482 int rc = shutdown(pThis->LocalSocket, SHUT_RDWR); 483 AssertRC(rc == 0); NOREF(rc); 484 485 rc = close(pThis->LocalSocket); 486 Assert(rc == 0); 487 pThis->LocalSocket = -1; 488 } 489 if ( pThis->fIsServer 490 && pThis->pszLocation) 491 RTFileDelete(pThis->pszLocation); 492 #endif /* !RT_OS_WINDOWS */ 493 494 MMR3HeapFree(pThis->pszLocation); 495 pThis->pszLocation = NULL; 496 497 /* 498 * Wait for the thread. 499 */ 500 if (pThis->ListenThread != NIL_RTTHREAD) 501 { 502 int rc = RTThreadWait(pThis->ListenThread, 30000, NULL); 503 if (RT_SUCCESS(rc)) 504 pThis->ListenThread = NIL_RTTHREAD; 505 else 506 LogRel(("NamedPipe%d: listen thread did not terminate (%Rrc)\n", pDrvIns->iInstance, rc)); 507 } 508 509 /* 510 * The last bits of cleanup. 511 */ 512 #ifdef RT_OS_WINDOWS 513 if (pThis->ListenSem != NIL_RTSEMEVENT) 514 { 515 RTSemEventMultiDestroy(pThis->ListenSem); 516 pThis->ListenSem = NIL_RTSEMEVENT; 517 } 518 #endif 466 519 } 467 520 … … 474 527 static DECLCALLBACK(int) drvNamedPipeConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) 475 528 { 476 int rc;477 char *pszLocation = NULL;478 529 PDRVNAMEDPIPE pThis = PDMINS_2_DATA(pDrvIns, PDRVNAMEDPIPE); 479 530 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); … … 487 538 #ifdef RT_OS_WINDOWS 488 539 pThis->NamedPipe = INVALID_HANDLE_VALUE; 540 pThis->ListenSem = NIL_RTSEMEVENTMULTI; 541 pThis->OverlappedWrite.hEvent = NULL; 542 pThis->OverlappedRead.hEvent = NULL; 489 543 #else /* !RT_OS_WINDOWS */ 490 544 pThis->LocalSocketServer = -1; … … 500 554 501 555 /* 502 * Read the configuration.556 * Validate and read the configuration. 503 557 */ 504 if (!CFGMR3AreValuesValid(pCfg, "Location\0IsServer\0")) 505 { 506 rc = VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES; 507 goto l_out; 508 } 509 510 rc = CFGMR3QueryStringAlloc(pCfg, "Location", &pszLocation); 558 PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "Location|IsServer", ""); 559 560 int rc = CFGMR3QueryStringAlloc(pCfg, "Location", &pThis->pszLocation); 511 561 if (RT_FAILURE(rc)) 512 { 513 AssertMsgFailed(("Configuration error: query \"Location\" resulted in %Rrc.\n", rc)); 514 goto l_out; 515 } 516 pThis->pszLocation = pszLocation; 517 518 bool fIsServer; 519 rc = CFGMR3QueryBool(pCfg, "IsServer", &fIsServer); 562 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, 563 N_("Configuration error: querying \"Location\" resulted in %Rrc"), rc); 564 rc = CFGMR3QueryBool(pCfg, "IsServer", &pThis->fIsServer); 520 565 if (RT_FAILURE(rc)) 521 { 522 AssertMsgFailed(("Configuration error: query \"IsServer\" resulted in %Rrc.\n", rc)); 523 goto l_out; 524 } 525 pThis->fIsServer = fIsServer; 526 527 #ifdef RT_OS_WINDOWS 528 if (fIsServer) 529 { 530 HANDLE hPipe = CreateNamedPipe(pThis->pszLocation, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 32, 32, 10000, NULL); 531 if (hPipe == INVALID_HANDLE_VALUE) 566 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, 567 N_("Configuration error: querying \"IsServer\" resulted in %Rrc"), rc); 568 569 /* 570 * Create/Open the pipe. 571 */ 572 #ifdef RT_OS_WINDOWS 573 if (pThis->fIsServer) 574 { 575 pThis->NamedPipe = CreateNamedPipe(pThis->pszLocation, 576 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 577 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 578 1, /*nMaxInstances*/ 579 32, /*nOutBufferSize*/ 580 32, /*nOutBufferSize*/ 581 10000, /*nDefaultTimeOut*/ 582 NULL); /* lpSecurityAttributes*/ 583 if (pThis->NamedPipe == INVALID_HANDLE_VALUE) 532 584 { 533 585 rc = RTErrConvertFromWin32(GetLastError()); 534 586 LogRel(("NamedPipe%d: CreateNamedPipe failed rc=%Rrc\n", pThis->pDrvIns->iInstance)); 535 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create named pipe %s"), pDrvIns->iInstance, pszLocation); 536 } 537 pThis->NamedPipe = hPipe; 538 539 rc = RTSemEventCreate(&pThis->ListenSem); 540 AssertRC(rc); 541 542 rc = RTThreadCreate(&pThis->ListenThread, drvNamedPipeListenLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SerPipe"); 543 if RT_FAILURE(rc) 544 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create listening thread"), pDrvIns->iInstance); 587 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create named pipe %s"), 588 pDrvIns->iInstance, pThis->pszLocation); 589 } 590 591 rc = RTSemEventMultiCreate(&pThis->ListenSem); 592 AssertRCReturn(rc); 593 594 rc = RTThreadCreate(&pThis->ListenThread, drvNamedPipeListenLoop, (void *)pThis, 0, 595 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SerPipe"); 596 if (RT_FAILURE(rc)) 597 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create listening thread"), 598 pDrvIns->iInstance); 545 599 546 600 } … … 548 602 { 549 603 /* Connect to the named pipe. */ 550 HANDLE hPipe = CreateFile(pThis->pszLocation, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 551 if (hPipe == INVALID_HANDLE_VALUE) 604 pThis->NamedPipe = CreateFile(pThis->pszLocation, GENERIC_READ | GENERIC_WRITE, 0, NULL, 605 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 606 if (pThis->NamedPipe == INVALID_HANDLE_VALUE) 552 607 { 553 608 rc = RTErrConvertFromWin32(GetLastError()); 554 609 LogRel(("NamedPipe%d: CreateFile failed rc=%Rrc\n", pThis->pDrvIns->iInstance)); 555 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to connect to named pipe %s"), pDrvIns->iInstance, pszLocation);556 }557 pThis->NamedPipe = hPipe;610 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to connect to named pipe %s"), 611 pDrvIns->iInstance, pThis->pszLocation); 612 } 558 613 } 559 614 560 615 memset(&pThis->OverlappedWrite, 0, sizeof(pThis->OverlappedWrite)); 616 pThis->OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 617 AssertReturn(pThis->OverlappedWrite.hEvent != NULL, VERR_OUT_OF_RESOURCES); 618 561 619 memset(&pThis->OverlappedRead, 0, sizeof(pThis->OverlappedRead)); 562 pThis->OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);563 620 pThis->OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 621 AssertReturn(pThis->OverlappedRead.hEvent != NULL, VERR_OUT_OF_RESOURCES); 622 564 623 #else /* !RT_OS_WINDOWS */ 565 int s; 624 int s = socket(PF_UNIX, SOCK_STREAM, 0); 625 if (s == -1) 626 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, 627 N_("NamedPipe#%d failed to create local socket"), pDrvIns->iInstance); 628 566 629 struct sockaddr_un addr; 567 568 if ((s = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)569 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to create local socket"), pDrvIns->iInstance);570 571 630 memset(&addr, 0, sizeof(addr)); 572 631 addr.sun_family = AF_UNIX; 573 strncpy(addr.sun_path, p szLocation, sizeof(addr.sun_path)-1);574 575 if ( fIsServer)632 strncpy(addr.sun_path, pThis->pszLocation, sizeof(addr.sun_path) - 1); 633 634 if (pThis->fIsServer) 576 635 { 577 636 /* Bind address to the local socket. */ 578 RTFileDelete(pszLocation); 637 pThis->LocalSocketServer = s; 638 RTFileDelete(pThis->pszLocation); 579 639 if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) 580 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to bind to local socket %s"), pDrvIns->iInstance, pszLocation); 581 pThis->LocalSocketServer = s; 582 rc = RTThreadCreate(&pThis->ListenThread, drvNamedPipeListenLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SerPipe"); 583 if RT_FAILURE(rc) 584 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to create listening thread"), pDrvIns->iInstance); 640 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, 641 N_("NamedPipe#%d failed to bind to local socket %s"), 642 pDrvIns->iInstance, pThis->pszLocation); 643 rc = RTThreadCreate(&pThis->ListenThread, drvNamedPipeListenLoop, (void *)pThis, 0, 644 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SerPipe"); 645 if (RT_FAILURE(rc)) 646 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, 647 N_("NamedPipe#%d failed to create listening thread"), pDrvIns->iInstance); 585 648 } 586 649 else 587 650 { 588 651 /* Connect to the local socket. */ 652 pThis->LocalSocket = s; 589 653 if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) 590 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("NamedPipe#%d failed to connect to local socket %s"), pDrvIns->iInstance, pszLocation); 591 pThis->LocalSocket = s; 654 return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, 655 N_("NamedPipe#%d failed to connect to local socket %s"), 656 pDrvIns->iInstance, pThis->pszLocation); 592 657 } 593 658 #endif /* !RT_OS_WINDOWS */ 594 659 595 l_out: 596 if (RT_FAILURE(rc)) 597 { 598 if (pszLocation) 599 MMR3HeapFree(pszLocation); 600 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("NamedPipe#%d failed to initialize"), pDrvIns->iInstance); 601 } 602 603 LogFlow(("drvNamedPipeConstruct: location %s isServer %d\n", pszLocation, fIsServer)); 604 LogRel(("NamedPipe: location %s, %s\n", pszLocation, fIsServer ? "server" : "client")); 660 LogRel(("NamedPipe: location %s, %s\n", pThis->pszLocation, pThis->fIsServer ? "server" : "client")); 605 661 return VINF_SUCCESS; 606 662 }
Note:
See TracChangeset
for help on using the changeset viewer.