VirtualBox

Changeset 84157 in vbox for trunk/src/VBox/Devices/Serial


Ignore:
Timestamp:
May 6, 2020 9:22:39 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
137758
Message:

Devices/Serial/DrvTCP: Don't block the guest if there is no one connected in server mode because the serial write buffer is full and doesn't get drained

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Serial/DrvTCP.cpp

    r83584 r84157  
    133133
    134134
     135/**
     136 * Checks the wakeup pipe for events.
     137 *
     138 * @returns VBox status code.
     139 * @param   pThis                   The TCP driver instance.
     140 * @param   fEvts                   Event mask to set if a new connection arrived.
     141 */
     142static int drvTcpWakeupPipeCheckForRequest(PDRVTCP pThis, uint32_t fEvts)
     143{
     144    uint8_t bReason;
     145    size_t cbRead = 0;
     146    int rc = RTPipeRead(pThis->hPipeWakeR, &bReason, 1, &cbRead);
     147    if (rc == VINF_TRY_AGAIN) /* Nothing there so we are done here. */
     148        rc = VINF_SUCCESS;
     149    else if (RT_SUCCESS(rc))
     150    {
     151        if (bReason == DRVTCP_WAKEUP_REASON_EXTERNAL)
     152            rc = VERR_INTERRUPTED;
     153        else if (bReason == DRVTCP_WAKEUP_REASON_NEW_CONNECTION)
     154        {
     155            Assert(pThis->hTcpSock == NIL_RTSOCKET);
     156
     157            /* Read the socket handle. */
     158            RTSOCKET hTcpSockNew = NIL_RTSOCKET;
     159            rc = RTPipeReadBlocking(pThis->hPipeWakeR, &hTcpSockNew, sizeof(hTcpSockNew), NULL);
     160            AssertRC(rc);
     161
     162            /* Always include error event. */
     163            fEvts |= RTPOLL_EVT_ERROR;
     164            rc = RTPollSetAddSocket(pThis->hPollSet, hTcpSockNew,
     165                                    fEvts, DRVTCP_POLLSET_ID_SOCKET);
     166            if (RT_SUCCESS(rc))
     167                pThis->hTcpSock = hTcpSockNew;
     168        }
     169        else
     170            AssertMsgFailed(("Unknown wakeup reason in pipe %u\n", bReason));
     171    }
     172
     173    return rc;
     174}
     175
     176
    135177/** @interface_method_impl{PDMISTREAM,pfnPoll} */
    136178static DECLCALLBACK(int) drvTcpPoll(PPDMISTREAM pInterface, uint32_t fEvts, uint32_t *pfEvts, RTMSINTERVAL cMillies)
     
    147189        rc = RTPollSetEventsChange(pThis->hPollSet, DRVTCP_POLLSET_ID_SOCKET, fEvts);
    148190        AssertRC(rc);
     191    }
     192    else
     193    {
     194        /*
     195         * Check whether new connection arrived first so we don't miss it in case
     196         * the guest is constantly writing data and we always end up here.
     197         */
     198        rc = drvTcpWakeupPipeCheckForRequest(pThis, fEvts);
     199        if (   pThis->hTcpSock == NIL_RTSOCKET
     200            && (fEvts & RTPOLL_EVT_WRITE))
     201        {
     202            /*
     203             * Just pretend we can always write to not fill up any buffers and block the guest
     204             * from sending data.
     205             */
     206            *pfEvts |= RTPOLL_EVT_WRITE;
     207            return rc;
     208        }
    149209    }
    150210
     
    181241                {
    182242                    /* We got woken up, drain the pipe and return. */
    183                     uint8_t bReason;
    184                     size_t cbRead = 0;
    185                     rc = RTPipeRead(pThis->hPipeWakeR, &bReason, 1, &cbRead);
    186                     AssertRC(rc);
    187 
    188                     if (bReason == DRVTCP_WAKEUP_REASON_EXTERNAL)
    189                         rc = VERR_INTERRUPTED;
    190                     else if (bReason == DRVTCP_WAKEUP_REASON_NEW_CONNECTION)
    191                     {
    192                         Assert(pThis->hTcpSock == NIL_RTSOCKET);
    193 
    194                         /* Read the socket handle. */
    195                         RTSOCKET hTcpSockNew = NIL_RTSOCKET;
    196                         rc = RTPipeReadBlocking(pThis->hPipeWakeR, &hTcpSockNew, sizeof(hTcpSockNew), NULL);
    197                         AssertRC(rc);
    198 
    199                         /* Always include error event. */
    200                         fEvts |= RTPOLL_EVT_ERROR;
    201                         rc = RTPollSetAddSocket(pThis->hPollSet, hTcpSockNew,
    202                                                 fEvts, DRVTCP_POLLSET_ID_SOCKET);
    203                         if (RT_SUCCESS(rc))
    204                             pThis->hTcpSock = hTcpSockNew;
    205                     }
    206                     else
    207                         AssertMsgFailed(("Unknown wakeup reason in pipe %u\n", bReason));
     243                    rc = drvTcpWakeupPipeCheckForRequest(pThis, fEvts);
    208244                }
    209245                else
     
    319355        }
    320356    }
    321     else
    322         *pcbWrite = 0;
     357    /* else Just pretend we wrote everything to not block. */
    323358
    324359    LogFlow(("%s: returns %Rrc *pcbWrite=%zu\n", __FUNCTION__, rc, *pcbWrite));
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