The instruction: let data = udp_sock.recv(256, timeout = 10000) times out if a 1 byte message is received. If I change 256 to 1, it works. The code issues the send then the recv system call correctly and ignores the 1 byte response, checked with strace.
import os import std/net
let udp_sock = newSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) udp_sock.bindAddr(Port(0)) udp_sock.connect("redacted", Port(1234))
let data1 = paramStr(1)
nim --version Nim Compiler Version 2.2.10 [Linux: amd64] Compiled at 2026-04-24 Copyright (c) 2006-2026 by Andreas Rumpf
git hash: bfeb3146d1638b39f69007a4ae5a23e23ae4e5ef active boot switches: -d:release
strace output: strace: Process 12951 attached restart_syscall(<... resuming interrupted read ...>) = 0 sendto(3, "ddns,fbdfe59128c3739d3e700246c4b48e11", 37, MSG_NOSIGNAL, NULL, 0) = 37 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 10000) = 1 ([{fd=3, revents=POLLIN}]) recvfrom(3, "O", 4000, 0, NULL, NULL) = 1 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 8881) = 0 (Timeout) sendto(3, "ddns,fbdfe59128c3739d3e700246c4b48e11", 37, MSG_NOSIGNAL, NULL, 0) = 37 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 10000) = 1 ([{fd=3, revents=POLLIN}]) recvfrom(3, "O", 4000, 0, NULL, NULL) = 1 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 8877) = 0 (Timeout) sendto(3, "ddns,fbdfe59128c3739d3e700246c4b48e11", 37, MSG_NOSIGNAL, NULL, 0) = 37 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 10000) = 1 ([{fd=3, revents=POLLIN}]) recvfrom(3, "O", 4000, 0, NULL, NULL) = 1 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 8880) = 0 (Timeout) sendto(3, "ddns,fbdfe59128c3739d3e700246c4b48e11", 37, MSG_NOSIGNAL, NULL, 0) = 37 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 10000) = 1 ([{fd=3, revents=POLLIN}]) recvfrom(3, "O", 4000, 0, NULL, NULL) = 1 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 8880) = 0 (Timeout) sendto(3, "ddns,fbdfe59128c3739d3e700246c4b48e11", 37, MSG_NOSIGNAL, NULL, 0) = 37 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 10000) = 1 ([{fd=3, revents=POLLIN}]) recvfrom(3, "O", 4000, 0, NULL, NULL) = 1 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 8882) = 0 (Timeout) sendto(3, "ddns,fbdfe59128c3739d3e700246c4b48e11", 37, MSG_NOSIGNAL, NULL, 0) = 37 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 10000) = 1 ([{fd=3, revents=POLLIN}]) recvfrom(3, "O", 4000, 0, NULL, NULL) = 1 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 8879) = 0 (Timeout) sendto(3, "ddns,fbdfe59128c3739d3e700246c4b48e11", 37, MSG_NOSIGNAL, NULL, 0) = 37 poll([{fd=3, events=POLLIN|POLLPRI}], 1, 10000) = 1 ([{fd=3, revents=POLLIN}]) recvfrom(3, "O", 4000, 0, NULL, NULL) = 1
The echo statement never gets executed.
The recv(sock, data, size) function in net.nim will block untill size length data recieved if the socket buffer is enabled(which is default), this behaviour is a bit weird, but if you disable the socket buffer with newSocket(buffered = false), recv function will return immediately when there is some data available.
You can disable socket buffer or patch the net.nim file.