Skip to content

BulkCopy sub-second timeout truncates to zero and becomes infinite #285

Description

Describe the bug

BulkCopy::timeout(Duration) converts the supplied duration to whole seconds using timeout.as_secs() as u32 at mssql-tds/src/connection/bulk_copy.rs:435. Any positive duration below one second therefore becomes 0.

The bulk-copy timeout path defines 0 as an infinite timeout (BulkCopyTimeoutState::from_seconds(0) has no deadline), so requesting a short timeout silently disables timeout enforcement.

Steps to reproduce

  1. Configure a bulk copy with a positive sub-second timeout:
bulk_copy.timeout(Duration::from_millis(500));
  1. BulkCopy::timeout stores timeout_sec = 0 because Duration::as_secs() truncates fractional seconds.
  2. Start the bulk-copy operation.
  3. Observe that the timeout state treats 0 as infinite and never expires.

The conversion can also be demonstrated directly:

assert_eq!(Duration::from_millis(500).as_secs() as u32, 0);
assert!(BulkCopyTimeoutState::from_seconds(0)
    .remaining_duration()
    .is_none());

Expected behavior

A positive timeout must never become an unlimited timeout. Since the current public API accepts Duration, sub-second values should either retain their precision or be converted safely without producing the 0 = infinite sentinel (for example, round a positive fractional duration up to one second).

Actual behavior

Every timeout from 1 ms through 999 ms is truncated to 0 and interpreted as unlimited. A caller requesting the shortest timeout receives no timeout at all.

Version

main at 068efe7a

Affected crate

mssql-tds

Environment

All platforms; the defect is in platform-independent duration conversion.

Additional context

Related to #273, which tracks the broader class of arithmetic producing the 0 = unlimited sentinel. This issue isolates the directly reachable public BulkCopy::timeout(Duration) case so it can be fixed and regression-tested independently.

PR #270 does not address this path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions