Search code examples
windowsserial-portmodemhandshakeoverlapped-io

Cancel WaitCommEvent for overlapped serial I/O


I'm handling a non-standard modem via serial port in an overlapped manner. Besides reading from and writing to the telecommunication line, I have to check the control lines like CTS and DSR using the WaitCommEvent() function.

DWORD EvtMask;
/// (some scopes/levels ommitted)

const BOOL syncChange = WaitComEvent(hFile, &EvtMask, &overlapped);
if (!syncChange) {
    assert(GetLastError() == ERROR_IO_PENDING);
    /// *background activity* probably writing into EvtMask
    /// until overlapped.hEvent gets signalled
}

In the (practically all) cases the function call indicates *background activity*, I have to wait on the overlapped.hEvent to happen. Since I'm also waiting for events from alternative sources (like IPC caused by user input, program termination), I use the WaitForMuiltipleObjects() function. But, if the blocking wait is finished for other reasons than control line changes, how can I stop the background activity on EvtMask? The code I'm based on, currently uses SetCommMask(hFile, 0), but I did not find a reliable reference for this being appropriate.

I also observe cases where changes to control lines are not supported properly (driver?, VM?), so I have to do a sliced wait with in-between checking.

What must be done to safely leave the scope where the variable EvtMask is declared?


Solution

  • The code you have is correct, and fully supported by the documentation, which clearly says:

    If a process attempts to change the device handle's event mask by using the SetCommMask function while an overlapped WaitCommEvent operation is in progress, WaitCommEvent returns immediately.

    I've used this fact on both "real" serial ports, and USB virtual serial port emulations, and it works reliably.

    (In my particular case, I was watching for EV_TXEMPTY so that I could guarantee a minimal separation between certain transmissions on the wire)