VirtualBox

Changeset 71987 in vbox for trunk


Ignore:
Timestamp:
Apr 23, 2018 4:54:18 PM (7 years ago)
Author:
vboxsync
Message:

Serial/DrvChar: Use critical section to protect send path against sending stale data under certain circumstances

File:
1 edited

Legend:

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

    r69500 r71987  
    3232#include <iprt/poll.h>
    3333#include <iprt/stream.h>
     34#include <iprt/critsect.h>
    3435#include <iprt/semaphore.h>
    3536#include <iprt/uuid.h>
     
    7374    /** Event semaphore for the read relay thread. */
    7475    RTSEMEVENT                  hEvtSemRead;
     76    /** Critical section protection the send part. */
     77    RTCRITSECT                  CritSectSend;
    7578
    7679    /** Internal send FIFO queue */
     
    120123    PDRVCHAR pThis = RT_FROM_MEMBER(pInterface, DRVCHAR, ICharConnector);
    121124    const char *pbBuffer = (const char *)pvBuf;
     125    int rc = VINF_SUCCESS;
    122126
    123127    LogFlow(("%s: pvBuf=%#p cbWrite=%d\n", __FUNCTION__, pvBuf, cbWrite));
    124128
    125     for (uint32_t i = 0; i < cbWrite; i++)
     129    RTCritSectEnter(&pThis->CritSectSend);
     130
     131    for (uint32_t i = 0; i < cbWrite && RT_SUCCESS(rc); i++)
    126132    {
    127         if (ASMAtomicXchgBool(&pThis->fSending, true))
    128             return VERR_BUFFER_OVERFLOW;
    129 
    130         pThis->u8SendByte = pbBuffer[i];
    131         pThis->pDrvStream->pfnPollInterrupt(pThis->pDrvStream);
    132         STAM_COUNTER_INC(&pThis->StatBytesWritten);
     133        if (!ASMAtomicXchgBool(&pThis->fSending, true))
     134        {
     135            pThis->u8SendByte = pbBuffer[i];
     136            pThis->pDrvStream->pfnPollInterrupt(pThis->pDrvStream);
     137            STAM_COUNTER_INC(&pThis->StatBytesWritten);
     138        }
     139        else
     140            rc = VERR_BUFFER_OVERFLOW;
    133141    }
    134     return VINF_SUCCESS;
     142
     143    RTCritSectLeave(&pThis->CritSectSend);
     144    return rc;
    135145}
    136146
     
    182192            if (fEvtsRecv & RTPOLL_EVT_WRITE)
    183193            {
     194                RTCritSectEnter(&pThis->CritSectSend);
    184195                Assert(pThis->fSending);
    185196
     
    206217                    break;
    207218                }
     219                RTCritSectLeave(&pThis->CritSectSend);
    208220            }
    209221
     
    358370    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
    359371
     372    if (RTCritSectIsInitialized(&pThis->CritSectSend))
     373        RTCritSectDelete(&pThis->CritSectSend);
     374
    360375    if (pThis->hEvtSemRead != NIL_RTSEMEVENT)
    361376    {
     
    393408    pThis->ICharConnector.pfnSetBreak       = drvCharSetBreak;
    394409
     410    int rc = RTCritSectInit(&pThis->CritSectSend);
     411    if (RT_FAILURE(rc))
     412        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     413                                   N_("Char#%d: Failed to create critical section"), pDrvIns->iInstance);
     414
    395415    /*
    396416     * Get the ICharPort interface of the above driver/device.
     
    404424     */
    405425    PPDMIBASE pBase;
    406     int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);
     426    rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);
    407427    if (RT_FAILURE(rc))
    408428        return rc; /* Don't call PDMDrvHlpVMSetError here as we assume that the driver already set an appropriate error */
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