VirtualBox

Changeset 73720 in vbox for trunk


Ignore:
Timestamp:
Aug 16, 2018 5:57:44 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
124399
Message:

Runtime/serialport-win.cpp: Fixes, can't use CancelIo because it applies to the whole device and not only to the overlapped read (the required CancelIoEx is only available with Vista+). Luckily COMSTAT provides us with the necessary information to avoid CancelIo. Also set proper COM timeouts so we can get true non blocking behavior

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/win/serialport-win.cpp

    r73635 r73720  
    166166        rc = RTErrConvertFromWin32(GetLastError());
    167167
     168    if (RT_SUCCESS(rc))
     169    {
     170        /*
     171         * Set timeouts for non blocking mode.
     172         * See https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_commtimeouts .
     173         */
     174        COMMTIMEOUTS ComTimeouts;
     175        RT_ZERO(ComTimeouts);
     176        ComTimeouts.ReadIntervalTimeout = MAXDWORD;
     177        if (!SetCommTimeouts(pThis->hDev, &ComTimeouts))
     178            rc = RTErrConvertFromWin32(GetLastError());
     179    }
     180
    168181    return rc;
    169182}
     
    441454    *pcbRead = 0;
    442455
    443     /*
    444      * Kick of an overlapped read.  It should return immediately if
    445      * there is bytes in the buffer.  If not, we'll cancel it and see
    446      * what we get back.
    447      */
    448     int rc = VINF_SUCCESS;
    449     BOOL fSucc = ResetEvent(pThis->OverlappedRead.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
    450     DWORD cbRead = 0;
    451     if (   cbToRead == 0
    452         || ReadFile(pThis->hDev, pvBuf,
    453                     cbToRead <= ~(DWORD)0 ? (DWORD)cbToRead : ~(DWORD)0,
    454                     &cbRead, &pThis->OverlappedRead))
    455     {
    456         *pcbRead = cbRead;
    457         rc = VINF_SUCCESS;
    458     }
    459     else if (GetLastError() == ERROR_IO_PENDING)
    460     {
    461         if (!CancelIo(pThis->hDev))
    462             WaitForSingleObject(pThis->OverlappedRead.hEvent, INFINITE);
    463         if (GetOverlappedResult(pThis->hDev, &pThis->OverlappedRead, &cbRead, TRUE /*fWait*/))
    464         {
    465             *pcbRead = cbRead;
    466             rc = VINF_SUCCESS;
    467         }
    468         else if (GetLastError() == ERROR_OPERATION_ABORTED)
    469         {
    470             *pcbRead = 0;
     456    /* Check whether there is data waiting in the input queue. */
     457    int rc = VINF_SUCCESS;
     458    COMSTAT ComStat; RT_ZERO(ComStat);
     459    if (ClearCommError(pThis->hDev, NULL, &ComStat))
     460    {
     461        if (ComStat.cbInQue > 0)
     462        {
     463            DWORD dwToRead = RT_MIN(ComStat.cbInQue, (DWORD)cbToRead);
     464            /* Kick of an overlapped read.  It should return immediately */
     465            BOOL fSucc = ResetEvent(pThis->OverlappedRead.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
     466            DWORD cbRead = 0;
     467            if (   cbToRead == 0
     468                || ReadFile(pThis->hDev, pvBuf, dwToRead,
     469                            &cbRead, &pThis->OverlappedRead))
     470                *pcbRead = cbRead;
     471            else if (GetLastError() == ERROR_IO_PENDING)
     472            {
     473                /* This shouldn't actually happen, so turn this into a synchronous read. */
     474                if (GetOverlappedResult(pThis->hDev, &pThis->OverlappedRead, &cbRead, TRUE /*fWait*/))
     475                    *pcbRead = cbRead;
     476                else
     477                    rc = RTErrConvertFromWin32(GetLastError());
     478            }
     479            else
     480                rc = RTErrConvertFromWin32(GetLastError());
     481        }
     482        else
    471483            rc = VINF_TRY_AGAIN;
    472         }
    473         else
    474             rc = RTErrConvertFromWin32(GetLastError());
    475484    }
    476485    else
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