VirtualBox

Changeset 83584 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Apr 6, 2020 9:57:12 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
136939
Message:

Devices/Serial/DrvTCP: Fix connection handling for the server case and avoid modifying the hTcpSock member from different threads during runtime (was modified from the listen and I/O thread in the server case without using atomics or any protection). Fix timeout handling in the poll handler (wasn't adjusted properly when poll returned for an internal event)

File:
1 edited

Legend:

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

    r82968 r83584  
    8181    /** Writing end of the wakeup pipe. */
    8282    RTPIPE              hPipeWakeW;
    83     /** Flag whether the socket is in the pollset. */
    84     bool                fTcpSockInPollSet;
    8583    /** Flag whether the send buffer is full nad it is required to wait for more
    8684     * space until there is room again. */
    8785    bool                fXmitBufFull;
    8886
     87    /** Number of connections active. */
     88    volatile uint32_t   cConnections;
    8989    /** Thread for listening for new connections. */
    9090    RTTHREAD            ListenThread;
     
    100100
    101101/**
     102 * Kicks any possibly polling thread to get informed about changes - extended version
     103 * sending additional data along with the wakeup reason.
     104 *
     105 * @returns VBOx status code.
     106 * @param   pThis                   The TCP driver instance.
     107 * @param   bReason                 The reason code to handle.
     108 * @param   pvData                  The additional to send along with the wakeup reason.
     109 * @param   cbData                  Number of bytes to send along.
     110 */
     111static int drvTcpPollerKickEx(PDRVTCP pThis, uint8_t bReason, const void *pvData, size_t cbData)
     112{
     113    size_t cbWritten = 0;
     114    int rc = RTPipeWriteBlocking(pThis->hPipeWakeW, &bReason, 1, &cbWritten);
     115    if (RT_SUCCESS(rc))
     116        rc = RTPipeWriteBlocking(pThis->hPipeWakeW, pvData, cbData, &cbWritten);
     117    return rc;
     118}
     119
     120
     121/**
    102122 * Kicks any possibly polling thread to get informed about changes.
    103123 *
     
    109129{
    110130    size_t cbWritten = 0;
    111     return RTPipeWrite(pThis->hPipeWakeW, &bReason, 1, &cbWritten);
     131    return RTPipeWriteBlocking(pThis->hPipeWakeW, &bReason, 1, &cbWritten);
    112132}
    113133
     
    121141    if (pThis->hTcpSock != NIL_RTSOCKET)
    122142    {
    123         if (!pThis->fTcpSockInPollSet)
    124         {
    125             rc = RTPollSetAddSocket(pThis->hPollSet, pThis->hTcpSock,
    126                                     fEvts, DRVTCP_POLLSET_ID_SOCKET);
    127             if (RT_SUCCESS(rc))
    128             {
    129                 pThis->fTcpSockInPollSet = true;
    130                 pThis->fXmitBufFull = false;
    131             }
    132         }
    133         else
    134         {
    135             /* Always include error event. */
    136             fEvts |= RTPOLL_EVT_ERROR;
    137             rc = RTPollSetEventsChange(pThis->hPollSet, DRVTCP_POLLSET_ID_SOCKET, fEvts);
    138             AssertRC(rc);
    139         }
     143        Assert(ASMAtomicReadU32(&pThis->cConnections) > 0);
     144
     145        /* Always include error event. */
     146        fEvts |= RTPOLL_EVT_ERROR;
     147        rc = RTPollSetEventsChange(pThis->hPollSet, DRVTCP_POLLSET_ID_SOCKET, fEvts);
     148        AssertRC(rc);
    140149    }
    141150
     
    146155            uint32_t fEvtsRecv = 0;
    147156            uint32_t idHnd = 0;
     157            uint64_t tsStartMs = RTTimeMilliTS();
     158            RTMSINTERVAL cThisWaitMs = cMillies;
    148159
    149160            /*
     
    157168            if (   (fEvts & RTPOLL_EVT_WRITE)
    158169                && !pThis->fXmitBufFull
    159                 && pThis->fTcpSockInPollSet)
    160                 cMillies = 0;
    161 
    162             rc = RTPoll(pThis->hPollSet, cMillies, &fEvtsRecv, &idHnd);
     170                && pThis->hTcpSock != NIL_RTSOCKET)
     171                cThisWaitMs = 0;
     172
     173            rc = RTPoll(pThis->hPollSet, cThisWaitMs, &fEvtsRecv, &idHnd);
     174
     175            /* Adjust remaining time to wait. */
     176            uint64_t tsPollSpanMs = RTTimeMilliTS() - tsStartMs;
     177            cMillies -= RT_MIN(cMillies, tsPollSpanMs);
    163178            if (RT_SUCCESS(rc))
    164179            {
     
    175190                    else if (bReason == DRVTCP_WAKEUP_REASON_NEW_CONNECTION)
    176191                    {
    177                         Assert(!pThis->fTcpSockInPollSet);
    178                         rc = RTPollSetAddSocket(pThis->hPollSet, pThis->hTcpSock,
     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,
    179202                                                fEvts, DRVTCP_POLLSET_ID_SOCKET);
    180203                        if (RT_SUCCESS(rc))
    181                             pThis->fTcpSockInPollSet = true;
     204                            pThis->hTcpSock = hTcpSockNew;
    182205                    }
    183206                    else
     
    199222                            RTSocketClose(pThis->hTcpSock);
    200223                        pThis->hTcpSock = NIL_RTSOCKET;
    201                         pThis->fTcpSockInPollSet = false;
     224                        ASMAtomicDecU32(&pThis->cConnections);
    202225                        /* Continue with polling. */
    203226                    }
     
    261284                    RTSocketClose(pThis->hTcpSock);
    262285                pThis->hTcpSock = NIL_RTSOCKET;
    263                 pThis->fTcpSockInPollSet = false;
    264286                rc = VINF_SUCCESS;
    265287            }
     
    338360        if (RT_SUCCESS(rc))
    339361        {
    340             if (pThis->hTcpSock != NIL_RTSOCKET)
     362            if (ASMAtomicReadU32(&pThis->cConnections) > 0)
    341363            {
    342364                LogRel(("DrvTCP%d: only single connection supported\n", pThis->pDrvIns->iInstance));
     
    345367            else
    346368            {
    347                 pThis->hTcpSock = hTcpSockNew;
     369                ASMAtomicIncU32(&pThis->cConnections);
     370
    348371                /* Inform the poller about the new socket. */
    349                 drvTcpPollerKick(pThis, DRVTCP_WAKEUP_REASON_NEW_CONNECTION);
     372                drvTcpPollerKickEx(pThis, DRVTCP_WAKEUP_REASON_NEW_CONNECTION, &hTcpSockNew, sizeof(hTcpSockNew));
    350373            }
    351374        }
     
    485508    pThis->pszLocation                  = NULL;
    486509    pThis->fIsServer                    = false;
     510    pThis->fXmitBufFull                 = false;
     511    pThis->cConnections                 = 0;
    487512
    488513    pThis->hTcpServ                     = NULL;
     
    492517    pThis->hPipeWakeR                   = NIL_RTPIPE;
    493518    pThis->hPipeWakeW                   = NIL_RTPIPE;
    494     pThis->fTcpSockInPollSet            = false;
    495519
    496520    pThis->ListenThread                 = NIL_RTTHREAD;
     
    591615                                       pDrvIns->iInstance, pThis->pszLocation);
    592616
    593         pThis->fTcpSockInPollSet = true;
     617        ASMAtomicIncU32(&pThis->cConnections);
    594618    }
    595619
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