VirtualBox

Changeset 58319 in vbox


Ignore:
Timestamp:
Oct 19, 2015 7:30:29 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
103517
Message:

localipc-posix.cpp: Turns out Linux also returns POLLIN+POLLHUP. Adjusted the HUP detection for WaitForData, ReadNB and Read.

File:
1 edited

Legend:

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

    r58318 r58319  
    682682
    683683/**
    684  * Checks if the socket has has a HUP condition.
     684 * Checks if the socket has has a HUP condition after reading zero bytes.
    685685 *
    686686 * @returns true if HUP, false if no.
     
    689689static bool rtLocalIpcPosixHasHup(PRTLOCALIPCSESSIONINT pThis)
    690690{
    691 #ifndef RT_OS_OS2
     691    int fdNative = RTSocketToNative(pThis->hSocket);
     692
     693#if !defined(RT_OS_OS2) && !defined(RT_OS_SOLARIS)
    692694    struct pollfd PollFd;
    693695    RT_ZERO(PollFd);
    694     PollFd.fd      = RTSocketToNative(pThis->hSocket);
    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. */
     696    PollFd.fd      = fdNative;
     697    PollFd.events  = POLLHUP;
     698    if (poll(&PollFd, 1, 0) <= 0)
     699        return false;
     700    if (!(PollFd.revents & (POLLHUP | POLLERR)))
     701        return false;
     702#else  /* RT_OS_OS2 || RT_OS_SOLARIS */
     703    /*
     704     * OS/2:    No native poll, do zero byte send to check for EPIPE.
     705     * Solaris: We don't get POLLHUP.
     706     */
    716707    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;
     708    ssize_t rcSend = send(fdNative, &bDummy, 0, 0);
     709    if (rcSend >= 0 || (errno != EPIPE && errno != ECONNRESET))
     710        return false;
     711#endif /* RT_OS_OS2 || RT_OS_SOLARIS */
     712
     713    /*
     714     * We've established EPIPE.  Now make sure there aren't any last bytes to
     715     * read that came in between the recv made by the caller and the disconnect.
     716     */
     717    uint8_t bPeek;
     718    ssize_t rcRecv = recv(fdNative, &bPeek, 1, MSG_DONTWAIT | MSG_PEEK);
     719    return rcRecv <= 0;
    722720}
    723721
     
    982980                    if (cFds >= 1)
    983981                    {
    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)
     982                        /* Linux 4.2.2 sets both POLLIN and POLLHUP when the pipe is
     983                           broken and but no more data to read.  Google hints at NetBSD
     984                           returning more sane values (POLLIN till no more data, then
     985                           POLLHUP).  Solairs OTOH, doesn't ever seem to return POLLHUP. */
     986                        fEvents = RTPOLL_EVT_READ;
     987                        if (   (PollFd.revents & (POLLHUP | POLLERR))
     988                            && !(PollFd.revents & POLLIN))
     989                            fEvents = RTPOLL_EVT_ERROR;
     990# if defined(RT_OS_SOLARIS)
     991                        else if (PollFd.revents & POLLIN)
     992# else
     993                        else if ((PollFd.revents & (POLLIN | POLLHUP)) == (POLLIN | POLLHUP))
     994# endif
    989995                        {
    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))
     996                            /* Check if there is actually data available. */
     997                            uint8_t bPeek;
     998                            ssize_t rcRecv = recv(PollFd.fd, &bPeek, 1, MSG_DONTWAIT | MSG_PEEK);
     999                            if (rcRecv <= 0)
    9951000                                fEvents = RTPOLL_EVT_ERROR;
    996                             else
    997                                 AssertMsg(rcSend == 0, ("rcSend=%zd errno=%d\n", rcSend, errno));
    998 # endif
    9991001                        }
    1000                         else
    1001                             fEvents = RTPOLL_EVT_ERROR;
    10021002                        rc = VINF_SUCCESS;
    10031003                    }
Note: See TracChangeset for help on using the changeset viewer.

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