VirtualBox

Ignore:
Timestamp:
Oct 19, 2015 6:58:35 PM (9 years ago)
Author:
vboxsync
Message:

localipc-posix.cpp: Must disable SIGPIPE as there is no way to supress it on solaris (and possible others). Broken pipe detection in WaitForData, ReadNB and Read requires extra effort on solaris as POLLHUP isn't returned. Applied same effort to OS/2.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/posix/localipc-posix.cpp

    r58305 r58318  
    5252#endif
    5353#include <fcntl.h>
     54#include <signal.h>
    5455#include <unistd.h>
    5556
     
    232233                {
    233234                    RTSocketSetInheritance(pThis->hSocket, false /*fInheritable*/);
     235                    signal(SIGPIPE, SIG_IGN); /* Required on solaris, at least. */
    234236
    235237                    uint8_t cbAddr;
     
    511513                {
    512514                    RTSocketSetInheritance(pThis->hSocket, false /*fInheritable*/);
     515                    signal(SIGPIPE, SIG_IGN); /* Required on solaris, at least. */
    513516
    514517                    struct sockaddr_un  Addr;
     
    690693    RT_ZERO(PollFd);
    691694    PollFd.fd      = RTSocketToNative(pThis->hSocket);
    692     PollFd.events  = POLLHUP;
    693     return poll(&PollFd, 1, 0) >= 1
    694        && (PollFd.revents & POLLHUP);
    695 
    696 #else /* RT_OS_OS2: */
    697     return true;
    698 #endif
     695    PollFd.events  = POLLHUP | POLLIN;
     696    if (poll(&PollFd, 1, 0) > 0)
     697    {
     698       if (PollFd.revents & POLLIN)
     699       {
     700# ifdef RT_OS_SOLARIS
     701           /* Solaris doesn't seem to set POLLHUP for disconnected unix domain
     702              sockets. So, we have to do extra stupid work here to detect it. */
     703           uint8_t bDummy;
     704           ssize_t rcSend = send(PollFd.fd, &bDummy, 0, MSG_DONTWAIT);
     705           if (rcSend < 0 && (errno == EPIPE || errno == ECONNRESET))
     706               return true;
     707           AssertMsg(rcSend == 0, ("rcSend=%zd errno=%d\n", rcSend, errno));
     708# endif
     709           return false;
     710       }
     711       Assert(PollFd.revents != 0);
     712       return true;
     713    }
     714#else  /* RT_OS_OS2 */
     715    /* No native poll, do zero byte send to check for EPIPE. */
     716    uint8_t bDummy;
     717    ssize_t rcSend = send(PollFd.fd, &bDummy, 0, 0);
     718    if (rcSend < 0 && (errno == EPIPE || errno == ECONNRESET))
     719        return true;
     720#endif /* RT_OS_OS2 */
     721    return false;
    699722}
    700723
     
    942965                    uint32_t fEvents = 0;
    943966#ifdef RT_OS_OS2
    944                     /* This doesn't give us any error condition on hangup. */
     967                    /* This doesn't give us any error condition on hangup, so use HUP check. */
    945968                    Log(("RTLocalIpcSessionWaitForData: Calling RTSocketSelectOneEx...\n"));
    946969                    rc = RTSocketSelectOneEx(pThis->hSocket, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, &fEvents, cMillies);
    947970                    Log(("RTLocalIpcSessionWaitForData: RTSocketSelectOneEx returns %Rrc, fEvents=%#x\n", rc, fEvents));
     971                    if (RT_SUCCESS(rc) && fEvents == RTPOLL_EVT_READ && rtLocalIpcPosixHasHup(pThis))
     972                        rc = VERR_BROKEN_PIPE;
    948973#else
    949 /** @todo RTSocketPoll */
     974/** @todo RTSocketPoll? */
    950975                    /* POLLHUP will be set on hangup. */
    951976                    struct pollfd PollFd;
     
    957982                    if (cFds >= 1)
    958983                    {
    959                         fEvents = PollFd.revents & (POLLHUP | POLLERR) ? RTPOLL_EVT_ERROR : RTPOLL_EVT_READ;
     984                        /* Solaris may flag both POLLIN and POLLHUP for pipes when there is more
     985                           input to read.  Also, solaris may give us POLLIN without POLLHUP even
     986                           if a unix domain socket is already disconnected.  So, extra solaris
     987                           hacks are necessary here in addition to prioritizing POLLIN. */
     988                        if (PollFd.revents & POLLIN)
     989                        {
     990                            fEvents = RTPOLL_EVT_READ;
     991# ifdef RT_OS_SOLARIS       /* Same hack as in rtLocalIpcPosixHasHup. */
     992                            uint8_t bDummy;
     993                            ssize_t rcSend = send(PollFd.fd, &bDummy, 0, MSG_DONTWAIT);
     994                            if (rcSend < 0 && (errno == EPIPE || errno == ECONNRESET))
     995                                fEvents = RTPOLL_EVT_ERROR;
     996                            else
     997                                AssertMsg(rcSend == 0, ("rcSend=%zd errno=%d\n", rcSend, errno));
     998# endif
     999                        }
     1000                        else
     1001                            fEvents = RTPOLL_EVT_ERROR;
    9601002                        rc = VINF_SUCCESS;
    9611003                    }
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette