Skip to content

Commit

Permalink
Clamp long timeouts on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
sirhcel committed Aug 1, 2024
1 parent bd2bf99 commit bc4596f
Showing 1 changed file with 10 additions and 2 deletions.
12 changes: 10 additions & 2 deletions src/windows/com.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,21 @@ impl SerialPort for COMPort {

fn set_timeout(&mut self, timeout: Duration) -> Result<()> {
let milliseconds = timeout.as_millis();
// In the way we are setting up timeouts here, a timeout_constant of MAXDWORD gets
// rejected. Let's clamp the timeout constant for values of MAXDWORD and above. See remarks
// at https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-commtimeouts.
//
// This effectively throws away accuracy for really long timeouts but at least preserves a
// long-ish timeout. But just casting to DWORD would result in presumably unexpected short
// and non-monotonic timeouts from cutting off the higher bits.
let timeout_constant = u128::min(milliseconds, MAXDWORD as u128 - 1) as DWORD;

let mut timeouts = COMMTIMEOUTS {
ReadIntervalTimeout: MAXDWORD,
ReadTotalTimeoutMultiplier: MAXDWORD,
ReadTotalTimeoutConstant: milliseconds as DWORD,
ReadTotalTimeoutConstant: timeout_constant,
WriteTotalTimeoutMultiplier: 0,
WriteTotalTimeoutConstant: milliseconds as DWORD,
WriteTotalTimeoutConstant: timeout_constant,
};

if unsafe { SetCommTimeouts(self.handle, &mut timeouts) } == 0 {
Expand Down

0 comments on commit bc4596f

Please sign in to comment.