Retain the existing timer backend for short scan deadlines

This commit is contained in:
bee committed 2026-10-01 18:15:05 +01:00
1 parent 62ed937768
commit b5fedf363a
5 files changed
+78 -17

No files matched your search

Generated
+64 -7
View File
@@ -103,6 +103,24 @@ version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4"
[[package]]
name = "async-io"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc"
dependencies = [
"autocfg",
"cfg-if",
"concurrent-queue",
"futures-io",
"futures-lite",
"parking",
"polling",
"rustix",
"slab",
"windows-sys 0.61.2",
]
[[package]]
name = "async-trait"
version = "0.1.86"
@@ -288,6 +306,15 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb474a9c3219a8254ead020421ecf1b90427f29b55f6aae9a2471fa62c126ef"
[[package]]
name = "concurrent-queue"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "cpufeatures"
version = "0.3.0"
@@ -521,6 +548,16 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
[[package]]
name = "futures-lite"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
dependencies = [
"futures-core",
"pin-project-lite",
]
[[package]]
name = "futures-macro"
version = "0.3.31"
@@ -544,12 +581,6 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
[[package]]
name = "futures-timer"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af43fadb8a98512d547e37b4e92e0ced13e205c061b87b4623eff01d918d6968"
[[package]]
name = "futures-util"
version = "0.3.31"
@@ -645,6 +676,12 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284"
[[package]]
name = "hickory-proto"
version = "0.24.4"
@@ -1120,6 +1157,12 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "parking"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
[[package]]
name = "parking_lot"
version = "0.12.3"
@@ -1189,6 +1232,20 @@ dependencies = [
"plotters-backend",
]
[[package]]
name = "polling"
version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218"
dependencies = [
"cfg-if",
"concurrent-queue",
"hermit-abi",
"pin-project-lite",
"rustix",
"windows-sys 0.61.2",
]
[[package]]
name = "portable-atomic"
version = "1.11.0"
@@ -1453,6 +1510,7 @@ dependencies = [
"ansi_term",
"anstream",
"anyhow",
"async-io",
"cidr-utils",
"clap",
"colored",
@@ -1461,7 +1519,6 @@ dependencies = [
"dirs",
"env_logger",
"futures",
"futures-timer",
"gcd",
"hickory-resolver",
"itertools 0.15.0",
+1 -1
View File
@@ -21,7 +21,7 @@ clap = { version = "4.6.1", features = ["derive", "wrap_help"] }
colored = "3.1.1"
tokio = { version = "1.53.1", features = ["rt", "net", "time"] }
futures = "0.3"
futures-timer = "3.0.4"
async-io = "2.4.0"
rlimit = "0.11.0"
log = "0.4.32"
env_logger = "0.11.10"
+8 -7
View File
@@ -15,7 +15,8 @@ runtime. Script execution runs after the runtime has been dropped. Port ordering
exclusions, retries, UDP payloads, closed-port reporting and CLI options retain
their existing implementations.
Timeouts and port intervals use the runtime-independent `futures-timer` crate.
Timeouts and port intervals retain `async_io::Timer`, the timer underneath
async-std, independently of the Tokio socket runtime.
An expired timer maps to `std::io::ErrorKind::TimedOut`. Socket errors retain
their original kind, so TCP refusal reporting and UDP timeout retries continue
to distinguish replies from failures. Successful TCP streams are converted to
@@ -23,8 +24,8 @@ standard streams, shut down in both directions, and dropped before another
attempt is polled.
Using Tokio's timers for short waits added approximately one millisecond per
interval in the first benchmark. `futures-timer` uses a shared helper thread and
OS waits, avoiding that extra rounding while keeping the async runtime responsive.
interval in the first benchmark. Retaining the existing timer avoids that extra
rounding while keeping the async runtime responsive.
Dropping a scan cancels its timers; runtime shutdown never has to wait for a
sleeping blocking task. Immediately ready I/O operations avoid timer allocation,
and the time spent polling a pending operation is charged to its original timeout.
@@ -71,10 +72,10 @@ owns its own runtime and performs blocking lookups.
The direct Tokio dependency enables only `rt`, `net`, and `time`; `test-util` is
enabled for deterministic tests with a paused clock. Tokio was already present
through Hickory. The existing `futures` dependency continues to provide
`FuturesUnordered`, `StreamExt` and future polling. The new `futures-timer` 3.0.4
dependency has no transitive dependencies on native targets; its purpose is to
preserve short timeout and interval performance. `async-std` is absent from the
resolved dependency tree.
`FuturesUnordered`, `StreamExt` and future polling. `async-io` becomes a direct
dependency solely to retain the existing timer implementation and its short-wait
performance; socket I/O uses Tokio. `async-std` and its executor are absent from
the resolved dependency tree.
Regression tests cover successful operations (including zero-byte responses),
preservation of I/O errors, timeout cancellation, immediate results at a zero
+4 -1
View File
@@ -165,7 +165,10 @@ impl Scanner {
// Tokio's millisecond rounding adds about 1 ms to each short interval.
// This cancellable delay keeps the requested spacing without blocking
// the async runtime or accumulating that rounding on every port.
self.run_with_delay(futures_timer::Delay::new).await
self.run_with_delay(|interval| async move {
async_io::Timer::after(interval).await;
})
.await
}
/// Supplying the delay lets tests verify spacing with a virtual clock.
+1 -1
View File
@@ -20,7 +20,7 @@ pub(super) async fn io_timeout<T>(
// Charge socket setup to the original deadline. The timer uses OS waits
// without rounding each short timeout up to Tokio's next millisecond tick.
let delay = futures_timer::Delay::new(duration.saturating_sub(started.elapsed()));
let delay = async_io::Timer::after(duration.saturating_sub(started.elapsed()));
match select(operation, delay).await {
Either::Left((result, _)) => result,
Either::Right(_) => Err(io::Error::new(io::ErrorKind::TimedOut, "future timed out")),