Skip to content

fix(ports): send the ICMP timeout in the unit each ping expects - #3677

Merged
nicolargo merged 1 commit into
nicolargo:developfrom
ntdatt812:fix/ports-icmp-timeout-arg
Aug 26, 2026
Merged

nicolargo merged 1 commit into
nicolargo:developfrom
ntdatt812:fix/ports-icmp-timeout-arg

Conversation

@ntdatt812

Copy link
Copy Markdown
Contributor

Windows: the timeout is a thousand times too small

_port_scan_icmp() passes the configured timeout straight to ping:

if WINDOWS:
    timeout_opt = '-w'
...
cmd = ['ping', count_opt, '1', timeout_opt, str(self._resolv_name(port['timeout'])), ...]

Windows ping -w is documented as "Timeout in milliseconds to wait for each reply". -W (Linux) and -t (macOS/BSD) are in seconds. So timeout = 3 — the default in glances.conf — becomes a 3 ms deadline on Windows.

Measured on Windows 11, two hosts that answer comfortably inside 3 seconds:

host RTT ping -n 1 -w 3 ping -n 1 -w 3000
200.160.2.3 350 ms exit 1 exit 0
139.130.4.5 168 ms exit 1 exit 0

A non-zero exit lands in port['status'] = False, i.e. the host shows as offline.

Windows clamps the actual wait to roughly 50 ms, which is why this hides on a LAN:

-w 3     -> elapsed 50 ms      (against a black-holed IP)
-w 3000  -> elapsed 2985 ms

So 8.8.8.8 at 35 ms still answers in time, and anything further away is silently reported down. That matches the symptom of remote hosts flapping to offline on Windows while the same config is fine on Linux.

The same argument also goes through the DNS resolver

str(self._resolv_name(port['timeout']))

_resolv_name() runs socket.gethostbyname(). The timeout is a number of seconds, not a host — ports_list.py builds it with int(...), so the call can only raise:

>>> socket.gethostbyname(3)
TypeError: gethostbyname() argument 1 must be str, bytes or bytearray, not int

_resolv_name swallows that and returns the value unchanged, so nothing breaks today — but every ICMP check pays for a pointless call and writes a misleading Cannot convert 3 to IP address into the debug log.

The fix

Build the timeout argument next to the option that consumes it, in that option's own unit, and stop routing it through the resolver. -W and -t keep passing seconds through unchanged.

Tests

Four cases added to tests/test_plugin_ports.py, driving ThreadScanner._port_scan_icmp with subprocess.check_call captured:

  • Windows → ['ping', '-n', '1', '-w', '3000', 'example.net']
  • Linux → ['ping', '-c', '1', '-W', '3', 'example.net']
  • macOS/BSD → ['ping', '-c', '1', '-t', '3', 'example.net']
  • only the host reaches _resolv_name

Mutation-checked — reverting the source turns exactly the two affected cases red and leaves the two passthrough cases green:

FAILED TestIcmpPingCommand::test_windows_timeout_is_expressed_in_milliseconds
FAILED TestIcmpPingCommand::test_timeout_is_not_sent_through_the_name_resolver
2 failed, 11 passed

ruff check and ruff format --check clean.

Two problems on the same argument.

Windows 'ping -w' is a per-reply timeout in **milliseconds**, not
seconds, so a configured 'timeout = 3' became a 3 ms deadline. Measured
against two hosts that answer well within 3 seconds:

    200.160.2.3 (350 ms)  ping -n 1 -w 3    -> exit 1
    200.160.2.3 (350 ms)  ping -n 1 -w 3000 -> exit 0
    139.130.4.5 (168 ms)  ping -n 1 -w 3    -> exit 1
    139.130.4.5 (168 ms)  ping -n 1 -w 3000 -> exit 0

Windows clamps the wait to about 50 ms, so a host on the LAN still
answers in time and the bug hides; anything further away is reported
offline. Multiply by 1000 on Windows and leave -W/-t in seconds.

The timeout was also passed through _resolv_name(), which runs
socket.gethostbyname() on it. It is a number of seconds, not a host: the
lookup can only fail, and it logs a misleading 'Cannot convert 3 to IP
address' on every ICMP check.
@nicolargo nicolargo added this to the Glances 4.5.7 milestone Aug 26, 2026
@nicolargo
nicolargo merged commit 00bbe40 into nicolargo:develop Aug 26, 2026
17 of 19 checks passed
@nicolargo

Copy link
Copy Markdown
Owner

Thanks for the PR @ntdatt812

I hate Windows :)

Merged into develop !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants