NetBSD Problem Report #60443
From www@netbsd.org Sun Jul 12 07:58:11 2026
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
client-signature RSA-PSS (2048 bits) client-digest SHA256)
(Client CN "mail.netbsd.org", Issuer "YR2" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id 5D4581A923E
for <gnats-bugs@gnats.NetBSD.org>; Sun, 12 Jul 2026 07:58:11 +0000 (UTC)
Message-Id: <20260712075810.14B281A923F@mollari.NetBSD.org>
Date: Sun, 12 Jul 2026 07:58:10 +0000 (UTC)
From: rvp@SDF.ORG
Reply-To: rvp@SDF.ORG
To: gnats-bugs@NetBSD.org
Subject: ftp ASCII transfers are too slow
X-Send-Pr-Version: www-1.0
X-From4GNATS: "rvp@SDF.ORG via gnats" <gnats-admin@NetBSD.org>
>Number: 60443
>Category: bin
>Synopsis: ftp ASCII transfers are too slow
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Jul 12 08:00:00 +0000 2026
>Last-Modified: Sun Jul 19 08:15:00 +0000 2026
>Originator: RVP
>Release: NetBSD/amd64 11.99.6
>Organization:
>Environment:
NetBSD/amd64 11.99.6
>Description:
FTP ASCII transfers seem to interact badly with Nagle's algorithm
because ASCII xfers rely on libc's BUFSIZ (1KB) internal buffer.
If you write 1KB at a time (relatively slowly because you're doing
getc(3)/putc(3) to locale '\n'), then it looks the 200ms Nagle timeout
comes into play.
At that's what it seems to me from looking at the tcpdump packet times.
>How-To-Repeat:
1. Create a big text file.
dd if=/dev/urandom bs=1m count=100 | sed -n l > in.txt
2. Run ftpd.
/usr/libexec/ftpd -Ddl
3. Run tcpdump to capture packet times.
4. Get or Put the file--active or passive mode don't matter.
Reduce `xferbuf' to 8192 to make the xfer crawl real quick.
Also turn `progress' off. so that interrupts don't confound things.
>Fix:
You need 2 patches. One for ftp(1) and a similar one for ftpd(8).
---START patch ftp(1)---
diff -urN usr.bin/ftp.orig/ftp.c usr.bin/ftp/ftp.c
--- usr.bin/ftp.orig/ftp.c 2026-02-07 03:55:18.973125260 +0000
+++ usr.bin/ftp/ftp.c 2026-02-08 15:51:14.124404272 +0000
@@ -1728,6 +1728,23 @@
return (1);
}
+static FILE *
+ftp_fdopen(int fd, const char *lmode)
+{
+ enum { BSIZ = XFERBUFMIN * 4 }; /* 4K (any >MTU) */
+ FILE *fp;
+ void* buf;
+
+ if ((fp = fdopen(fd, lmode)) == NULL)
+ return NULL;
+ if ((buf = ftp_malloc(BSIZ)) == NULL) {
+ fclose(fp);
+ return NULL;
+ }
+ (void)setvbuf(fp, buf, _IOFBF, BSIZ);
+ return fp;
+}
+
FILE *
dataconn(const char *lmode)
{
@@ -1738,7 +1755,7 @@
socklen_t fromlen;
if (passivemode) /* passive data connection */
- return (fdopen(data, lmode));
+ return (ftp_fdopen(data, lmode));
/* active mode data connection */
@@ -1798,7 +1815,7 @@
}
}
#endif
- return (fdopen(data, lmode));
+ return (ftp_fdopen(data, lmode));
dataconn_failed:
(void)close(data);
---END patch ftp(1)---
---START patch ftpd(8)---
diff -urN libexec/ftpd.orig/ftpd.c libexec/ftpd/ftpd.c
--- libexec/ftpd.orig/ftpd.c 2025-06-28 04:00:41.032045996 +0000
+++ libexec/ftpd/ftpd.c 2026-02-08 15:35:04.378214731 +0000
@@ -1917,6 +1917,23 @@
}
static FILE *
+ftp_fdopen(int fd, const char *lmode)
+{
+ enum { BSIZ = FTP_BUFLEN * 8 }; /* 4KB (any >MTU) */
+ FILE *fp;
+ void* buf;
+
+ if ((fp = fdopen(fd, lmode)) == NULL)
+ return NULL;
+ if ((buf = malloc(BSIZ)) == NULL) {
+ fclose(fp);
+ return NULL;
+ }
+ (void)setvbuf(fp, buf, _IOFBF, BSIZ);
+ return fp;
+}
+
+static FILE *
getdatasock(const char *fmode)
{
int on, s, t, tries;
@@ -1924,7 +1941,7 @@
on = 1;
if (data >= 0)
- return (fdopen(data, fmode));
+ return (ftp_fdopen(data, fmode));
if (! dropprivs) {
if (seteuid((uid_t)0) < 0) {
syslog(LOG_NOTICE, "getdatasock: can't seteuid 0: %m");
@@ -1979,7 +1996,7 @@
syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
}
#endif
- return (fdopen(s, fmode));
+ return (ftp_fdopen(s, fmode));
bad:
/* Return the real value of errno (close may change it) */
t = errno;
@@ -2044,13 +2061,13 @@
#endif
reply(150, "Opening %s mode data connection for '%s'%s.",
type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
- return (fdopen(pdata, fmode));
+ return (ftp_fdopen(pdata, fmode));
}
if (data >= 0) {
reply(125, "Using existing data connection for '%s'%s.",
name, sizebuf);
usedefault = 1;
- return (fdopen(data, fmode));
+ return (ftp_fdopen(data, fmode));
}
if (usedefault)
data_dest = his_addr;
---END patch ftpd(8)---
>Audit-Trail:
From: mlelstv@serpens.de (Michael van Elst)
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60443: ftp ASCII transfers are too slow
Date: Sun, 12 Jul 2026 11:53:39 -0000 (UTC)
gnats-admin@NetBSD.org ("rvp@SDF.ORG via gnats") writes:
>FTP ASCII transfers seem to interact badly with Nagle's algorithm
>because ASCII xfers rely on libc's BUFSIZ (1KB) internal buffer.
I doubt that Nagle's algorithm has any effect here. After all,
it would just improve throughput at the cost of latency.
What you see is the higher overhead from stdio.
E.g.:
ftp> get in.txt
local: in.txt remote: in.txt
229 Entering Extended Passive Mode (|||62337|)
150 Opening ASCII mode data connection for 'in.txt' (306788817 bytes).
226 Transfer complete.
312122680 bytes received in 00:08 (34.99 MiB/s)
vs.
ftp> get in.txt
local: in.txt remote: in.txt
229 Entering Extended Passive Mode (|||62335|)
150 Opening BINARY mode data connection for 'in.txt' (306788817 bytes).
226 Transfer complete.
306788817 bytes received in 00:08 (33.36 MiB/s)
and (with kern.sofixedbuf=0 to keep TCP autoscaling enabled):
ftp> get in.txt
local: in.txt remote: in.txt
229 Entering Extended Passive Mode (|||62332|)
150 Opening ASCII mode data connection for 'in.txt' (306788817 bytes).
226 Transfer complete.
312122680 bytes received in 00:08 (33.22 MiB/s)
vs.
ftp> get in.txt
local: in.txt remote: in.txt
229 Entering Extended Passive Mode (|||62331|)
150 Opening BINARY mode data connection for 'in.txt' (306788817 bytes).
226 Transfer complete.
306788817 bytes received in 00:05 (53.21 MiB/s)
In all cases the ftpd was CPU limited (on a 1.6GHz Atom N3150).
For ASCII transfers, about 44% of a core are spent in usermode.
For BINARY transfers, less than 1% of a core is spent in usermode, but
the CPU spends about twice the time in system mode.
The client shows similar behaviour. Funneling data through stdio
takes lots of time in usermode and time spent in system mode
about doubles for the binary transfer.
> time ftp -x 8192 -V ftp://ftp:user@fud.local/pub/in.txt\;type=a
2.370u 0.671s 0:08.63 35.2% 0+0k 0+14io 0pf+0w
> time ftp -x 8192 -V ftp://ftp:user@fud.local/pub/in.txt\;type=i
0.050u 1.234s 0:08.94 14.3% 0+1k 0+16io 0pf+0w
and with autoscaling:
> time ftp -x 8192 -V ftp://ftp:user@fud.local/pub/in.txt\;type=a
2.352u 0.713s 0:09.42 32.4% 0+0k 0+14io 0pf+0w
> time ftp -x 8192 -V ftp://ftp:user@fud.local/pub/in.txt\;type=i
0.038u 1.072s 0:05.42 20.2% 1+1k 0+10io 0pf+0w
Now, why does system time increase? It should process the same
amount of data, and the system call overhead should be larger
for ASCII transfers. Maybe that's more lock contention in the kernel
at higher speeds, but the lockstat numbers are not conclusive.
From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60443: ftp ASCII transfers are too slow
Date: Mon, 13 Jul 2026 01:36:03 +0000 (UTC)
On Sun, 12 Jul 2026, Michael van Elst via gnats wrote:
> gnats-admin@NetBSD.org ("rvp@SDF.ORG via gnats") writes:
>
> >FTP ASCII transfers seem to interact badly with Nagle's algorithm
> >because ASCII xfers rely on libc's BUFSIZ (1KB) internal buffer.
>
> I doubt that Nagle's algorithm has any effect here. After all,
> it would just improve throughput at the cost of latency.
>
> What you see is the higher overhead from stdio.
>
Right, of course stdio plays a part, but because, I think, of the 1KB at-a-time
writes. And, I reached for an interaction with Nagle because:
a) 200ms packet delay (see tcpdump log below).
b) situation improved if I used a 4KB stdio buffer.
c) things also zip along if I set TCP_NODELAY on the xfer sockets (see log).
> ftp> get in.txt
> local: in.txt remote: in.txt
> 229 Entering Extended Passive Mode (|||62337|)
> 150 Opening ASCII mode data connection for 'in.txt' (306788817 bytes).
> 226 Transfer complete.
> 312122680 bytes received in 00:08 (34.99 MiB/s)
> [...]
> In all cases the ftpd was CPU limited (on a 1.6GHz Atom N3150).
>
I get better speeds with both my patches on an
"Intel(R) Core(TM) i3-1005G1 CPU @ 1.20GHz"
Otherwise, with a large enough file, ASCII xfers eventually just crawls--like
settling on ~70KB/sec xfer rates.
I don't know how you're getting 35MB/sec w/o any tweaking. Michael, can you try
with both server and client on localhost like I did?
-RVP
---START tcpdump output---
04:42:56.720934 IP6 ::1.65426 > ::1.21: Flags [S], seq 62646337, win 32768, options [mss 33564,nop,wscale 3,sackOK,TS val 1 ecr 0], length 0
04:42:56.720954 IP6 ::1.21 > ::1.65426: Flags [S.], seq 59295266, ack 62646338, win 32768, options [mss 33564,nop,wscale 3,sackOK,TS val 1 ecr 1], length 0
04:42:56.720965 IP6 ::1.65426 > ::1.21: Flags [.], ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 0
04:42:56.726401 IP6 ::1.21 > ::1.65426: Flags [P.], seq 1:57, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 56: FTP: 220 localhost FTP server (NetBSD-ftpd 20230930) ready.
04:42:56.925619 IP6 ::1.65426 > ::1.21: Flags [.], ack 57, win 4096, options [nop,nop,TS val 1 ecr 1], length 0
04:42:58.819652 IP6 ::1.65426 > ::1.21: Flags [P.], seq 1:11, ack 57, win 4096, options [nop,nop,TS val 5 ecr 1], length 10: FTP: USER rvp
04:42:58.831280 IP6 ::1.21 > ::1.65426: Flags [P.], seq 57:122, ack 11, win 4096, options [nop,nop,TS val 5 ecr 5], length 65: FTP: 331 User rvp accepted, provide password for rvp@CoreBook.local.
04:42:59.030621 IP6 ::1.65426 > ::1.21: Flags [.], ack 122, win 4096, options [nop,nop,TS val 6 ecr 5], length 0
04:43:01.603623 IP6 ::1.65426 > ::1.21: Flags [P.], seq 11:26, ack 122, win 4096, options [nop,nop,TS val 11 ecr 5], length 15: FTP: PASS bh33ns11
04:43:01.692169 IP6 ::1.21 > ::1.65426: Flags [P.], seq 122:128, ack 26, win 4096, options [nop,nop,TS val 11 ecr 11], length 6: FTP: 230-
04:43:01.891621 IP6 ::1.65426 > ::1.21: Flags [.], ack 128, win 4096, options [nop,nop,TS val 11 ecr 11], length 0
04:43:01.891652 IP6 ::1.21 > ::1.65426: Flags [P.], seq 128:475, ack 26, win 4096, options [nop,nop,TS val 11 ecr 11], length 347: FTP: NetBSD 11.99.4 (COREBOOK_DIAG) #0: Sun Dec 7 04:08:07 UTC 2025
04:43:01.893119 IP6 ::1.65426 > ::1.21: Flags [P.], seq 26:32, ack 475, win 4096, options [nop,nop,TS val 11 ecr 11], length 6: FTP: SYST
04:43:01.893271 IP6 ::1.21 > ::1.65426: Flags [P.], seq 475:524, ack 32, win 4096, options [nop,nop,TS val 11 ecr 11], length 49: FTP: 215 UNIX Type: L8 Version: NetBSD-ftpd 20230930
04:43:01.893540 IP6 ::1.65426 > ::1.21: Flags [P.], seq 32:38, ack 524, win 4096, options [nop,nop,TS val 11 ecr 11], length 6: FTP: FEAT
04:43:01.893600 IP6 ::1.21 > ::1.65426: Flags [P.], seq 524:548, ack 38, win 4096, options [nop,nop,TS val 11 ecr 11], length 24: FTP: 211-Features supported
04:43:02.093622 IP6 ::1.65426 > ::1.21: Flags [.], ack 548, win 4096, options [nop,nop,TS val 12 ecr 11], length 0
04:43:02.093655 IP6 ::1.21 > ::1.65426: Flags [P.], seq 548:634, ack 38, win 4096, options [nop,nop,TS val 12 ecr 12], length 86: FTP: MDTM
04:43:02.293636 IP6 ::1.65426 > ::1.21: Flags [.], ack 634, win 4096, options [nop,nop,TS val 12 ecr 12], length 0
04:43:07.003663 IP6 ::1.65426 > ::1.21: Flags [P.], seq 38:46, ack 634, win 4096, options [nop,nop,TS val 22 ecr 12], length 8: FTP: TYPE A
04:43:07.003726 IP6 ::1.21 > ::1.65426: Flags [P.], seq 634:654, ack 46, win 4096, options [nop,nop,TS val 22 ecr 22], length 20: FTP: 200 Type set to A.
04:43:07.203615 IP6 ::1.65426 > ::1.21: Flags [.], ack 654, win 4096, options [nop,nop,TS val 22 ecr 22], length 0
04:43:13.003639 IP6 ::1.65426 > ::1.21: Flags [P.], seq 46:56, ack 654, win 4096, options [nop,nop,TS val 34 ecr 22], length 10: FTP: CWD /tmp
04:43:13.003733 IP6 ::1.21 > ::1.65426: Flags [P.], seq 654:683, ack 56, win 4096, options [nop,nop,TS val 34 ecr 34], length 29: FTP: 250 CWD command successful.
04:43:13.203610 IP6 ::1.65426 > ::1.21: Flags [.], ack 683, win 4096, options [nop,nop,TS val 34 ecr 34], length 0
04:43:20.163696 IP6 ::1.65426 > ::1.21: Flags [P.], seq 56:69, ack 683, win 4096, options [nop,nop,TS val 48 ecr 34], length 13: FTP: SIZE in.txt
04:43:20.163806 IP6 ::1.21 > ::1.65426: Flags [P.], seq 683:721, ack 69, win 4096, options [nop,nop,TS val 48 ecr 48], length 38: FTP: 550 in.txt: file too large for SIZE.
04:43:20.164028 IP6 ::1.65426 > ::1.21: Flags [P.], seq 69:75, ack 721, win 4096, options [nop,nop,TS val 48 ecr 48], length 6: FTP: EPSV
04:43:20.164176 IP6 ::1.21 > ::1.65426: Flags [P.], seq 721:769, ack 75, win 4096, options [nop,nop,TS val 48 ecr 48], length 48: FTP: 229 Entering Extended Passive Mode (|||65425|)
04:43:20.164443 IP6 ::1.65424 > ::1.65425: Flags [S], seq 1247060766, win 32768, options [mss 33564,nop,wscale 3,sackOK,TS val 1 ecr 0], length 0
04:43:20.164458 IP6 ::1.65425 > ::1.65424: Flags [S.], seq 1239190458, ack 1247060767, win 32768, options [mss 33564,nop,wscale 3,sackOK,TS val 1 ecr 1], length 0
04:43:20.164469 IP6 ::1.65424 > ::1.65425: Flags [.], ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 0
04:43:20.164506 IP6 ::1.65426 > ::1.21: Flags [P.], seq 75:88, ack 769, win 4096, options [nop,nop,TS val 48 ecr 48], length 13: FTP: RETR in.txt
04:43:20.164641 IP6 ::1.21 > ::1.65426: Flags [P.], seq 769:841, ack 88, win 4096, options [nop,nop,TS val 48 ecr 48], length 72: FTP: 150 Opening ASCII mode data connection for 'in.txt' (476494829 bytes).
04:43:20.164731 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 1:1025, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 1024
04:43:20.165003 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 1025:17409, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 16384
04:43:20.165027 IP6 ::1.65424 > ::1.65425: Flags [.], ack 17409, win 1920, options [nop,nop,TS val 1 ecr 1], length 0
04:43:20.165045 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 17409:18433, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 1024
04:43:20.165292 IP6 ::1.65424 > ::1.65425: Flags [.], ack 18433, win 3840, options [nop,nop,TS val 1 ecr 1], length 0
04:43:20.165308 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 18433:34817, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 16384
04:43:20.165529 IP6 ::1.65424 > ::1.65425: Flags [.], ack 34817, win 3840, options [nop,nop,TS val 1 ecr 1], length 0
04:43:20.165547 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 34817:46081, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 11264
04:43:20.165783 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 46081:62465, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 16384
04:43:20.165808 IP6 ::1.65424 > ::1.65425: Flags [.], ack 62465, win 2048, options [nop,nop,TS val 1 ecr 1], length 0
04:43:20.165834 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 62465:63489, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 1024
04:43:20.166023 IP6 ::1.65424 > ::1.65425: Flags [.], ack 63489, win 3968, options [nop,nop,TS val 1 ecr 1], length 0
04:43:20.166038 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 63489:74753, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 11264
04:43:20.166267 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 74753:91137, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 16384
04:43:20.166293 IP6 ::1.65424 > ::1.65425: Flags [.], ack 91137, win 2048, options [nop,nop,TS val 1 ecr 1], length 0
04:43:20.166311 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 91137:92161, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 1024
04:43:20.166463 IP6 ::1.65424 > ::1.65425: Flags [.], ack 92161, win 3968, options [nop,nop,TS val 1 ecr 1], length 0
04:43:20.166477 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 92161:103425, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 11264
04:43:20.166696 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 103425:119809, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 16384
04:43:20.166740 IP6 ::1.65424 > ::1.65425: Flags [.], ack 119809, win 2048, options [nop,nop,TS val 1 ecr 1], length 0
04:43:20.166761 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 119809:120833, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 1024
04:43:20.166920 IP6 ::1.65424 > ::1.65425: Flags [.], ack 120833, win 3968, options [nop,nop,TS val 1 ecr 1], length 0
04:43:20.166962 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 120833:135169, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 14336
04:43:20.364623 IP6 ::1.65426 > ::1.21: Flags [.], ack 841, win 4096, options [nop,nop,TS val 48 ecr 48], length 0
04:43:20.366588 IP6 ::1.65424 > ::1.65425: Flags [.], ack 135169, win 4096, options [nop,nop,TS val 1 ecr 1], length 0
04:43:20.366627 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 135169:148481, ack 1, win 4096, options [nop,nop,TS val 1 ecr 1], length 13312
04:43:20.566609 IP6 ::1.65424 > ::1.65425: Flags [.], ack 148481, win 4096, options [nop,nop,TS val 2 ecr 1], length 0
04:43:20.566638 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 148481:162817, ack 1, win 4096, options [nop,nop,TS val 2 ecr 2], length 14336
04:43:20.766615 IP6 ::1.65424 > ::1.65425: Flags [.], ack 162817, win 4096, options [nop,nop,TS val 2 ecr 2], length 0
04:43:20.766643 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 162817:176129, ack 1, win 4096, options [nop,nop,TS val 2 ecr 2], length 13312
04:43:20.966615 IP6 ::1.65424 > ::1.65425: Flags [.], ack 176129, win 4096, options [nop,nop,TS val 3 ecr 2], length 0
04:43:20.966643 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 176129:190465, ack 1, win 4096, options [nop,nop,TS val 3 ecr 3], length 14336
04:43:21.166615 IP6 ::1.65424 > ::1.65425: Flags [.], ack 190465, win 4096, options [nop,nop,TS val 3 ecr 3], length 0
04:43:21.166644 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 190465:203777, ack 1, win 4096, options [nop,nop,TS val 3 ecr 3], length 13312
04:43:21.366614 IP6 ::1.65424 > ::1.65425: Flags [.], ack 203777, win 4096, options [nop,nop,TS val 3 ecr 3], length 0
04:43:21.366641 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 203777:218113, ack 1, win 4096, options [nop,nop,TS val 3 ecr 3], length 14336
04:43:21.566615 IP6 ::1.65424 > ::1.65425: Flags [.], ack 218113, win 4096, options [nop,nop,TS val 4 ecr 3], length 0
04:43:21.566642 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 218113:231425, ack 1, win 4096, options [nop,nop,TS val 4 ecr 4], length 13312
04:43:21.766614 IP6 ::1.65424 > ::1.65425: Flags [.], ack 231425, win 4096, options [nop,nop,TS val 4 ecr 4], length 0
04:43:21.766643 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 231425:245761, ack 1, win 4096, options [nop,nop,TS val 4 ecr 4], length 14336
04:43:21.966614 IP6 ::1.65424 > ::1.65425: Flags [.], ack 245761, win 4096, options [nop,nop,TS val 5 ecr 4], length 0
04:43:21.966642 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 245761:259073, ack 1, win 4096, options [nop,nop,TS val 5 ecr 5], length 13312
04:43:22.166615 IP6 ::1.65424 > ::1.65425: Flags [.], ack 259073, win 4096, options [nop,nop,TS val 5 ecr 5], length 0
04:43:22.166643 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 259073:273409, ack 1, win 4096, options [nop,nop,TS val 5 ecr 5], length 14336
04:43:22.366622 IP6 ::1.65424 > ::1.65425: Flags [.], ack 273409, win 4096, options [nop,nop,TS val 5 ecr 5], length 0
04:43:22.366653 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 273409:286721, ack 1, win 4096, options [nop,nop,TS val 5 ecr 5], length 13312
04:43:22.566614 IP6 ::1.65424 > ::1.65425: Flags [.], ack 286721, win 4096, options [nop,nop,TS val 6 ecr 5], length 0
04:43:22.566643 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 286721:301057, ack 1, win 4096, options [nop,nop,TS val 6 ecr 6], length 14336
04:43:22.766617 IP6 ::1.65424 > ::1.65425: Flags [.], ack 301057, win 4096, options [nop,nop,TS val 6 ecr 6], length 0
04:43:22.766645 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 301057:314369, ack 1, win 4096, options [nop,nop,TS val 6 ecr 6], length 13312
04:43:22.966615 IP6 ::1.65424 > ::1.65425: Flags [.], ack 314369, win 4096, options [nop,nop,TS val 7 ecr 6], length 0
04:43:22.966644 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 314369:328705, ack 1, win 4096, options [nop,nop,TS val 7 ecr 7], length 14336
04:43:23.166607 IP6 ::1.65424 > ::1.65425: Flags [.], ack 328705, win 4096, options [nop,nop,TS val 7 ecr 7], length 0
04:43:23.166636 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 328705:342017, ack 1, win 4096, options [nop,nop,TS val 7 ecr 7], length 13312
04:43:23.366620 IP6 ::1.65424 > ::1.65425: Flags [.], ack 342017, win 4096, options [nop,nop,TS val 7 ecr 7], length 0
04:43:23.366660 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 342017:356353, ack 1, win 4096, options [nop,nop,TS val 7 ecr 7], length 14336
04:43:23.566617 IP6 ::1.65424 > ::1.65425: Flags [.], ack 356353, win 4096, options [nop,nop,TS val 8 ecr 7], length 0
04:43:23.566647 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 356353:369665, ack 1, win 4096, options [nop,nop,TS val 8 ecr 8], length 13312
04:43:23.766607 IP6 ::1.65424 > ::1.65425: Flags [.], ack 369665, win 4096, options [nop,nop,TS val 8 ecr 8], length 0
04:43:23.766636 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 369665:384001, ack 1, win 4096, options [nop,nop,TS val 8 ecr 8], length 14336
04:43:23.966614 IP6 ::1.65424 > ::1.65425: Flags [.], ack 384001, win 4096, options [nop,nop,TS val 9 ecr 8], length 0
04:43:23.966644 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 384001:397313, ack 1, win 4096, options [nop,nop,TS val 9 ecr 9], length 13312
04:43:24.166610 IP6 ::1.65424 > ::1.65425: Flags [.], ack 397313, win 4096, options [nop,nop,TS val 9 ecr 9], length 0
04:43:24.166639 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 397313:411649, ack 1, win 4096, options [nop,nop,TS val 9 ecr 9], length 14336
04:43:24.366616 IP6 ::1.65424 > ::1.65425: Flags [.], ack 411649, win 4096, options [nop,nop,TS val 9 ecr 9], length 0
04:43:24.366644 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 411649:424961, ack 1, win 4096, options [nop,nop,TS val 9 ecr 9], length 13312
04:43:24.566616 IP6 ::1.65424 > ::1.65425: Flags [.], ack 424961, win 4096, options [nop,nop,TS val 10 ecr 9], length 0
04:43:24.566645 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 424961:439297, ack 1, win 4096, options [nop,nop,TS val 10 ecr 10], length 14336
---END tcpdump output---
---START TCP_NODELAY log---
$ /tmp/obj/usr/src/usr.bin/ftp/ftp localhost
Trying [::1]:21 ...
Connected to localhost.
220 localhost FTP server (NetBSD-ftpd 20230930) ready.
Name (localhost:rvp):
331 User rvp accepted, provide password for rvp@CoreBook.local.
Password:
230-
NetBSD 11.99.6 (GENERIC) #0: Fri Jul 10 21:54:30 UTC 2026
Welcome to NetBSD!
This is a development snapshot of NetBSD for testing -- user beware!
Bug reports: https://www.NetBSD.org/support/send-pr.html
Donations to the NetBSD Foundation: https://www.NetBSD.org/donations/
230 User rvp logged in.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ascii
200 Type set to A.
ftp> progress
Progress bar off.
ftp> cd /tmp
250 CWD command successful.
ftp> get in.txt out.txt
local: out.txt remote: in.txt
229 Entering Extended Passive Mode (|||65505|)
150 Opening ASCII mode data connection for 'in.txt' (306795321 bytes).
226 Transfer complete.
312128515 bytes received in 00:02 (145.34 MiB/s)
ftp> put in.txt out.txt
local: in.txt remote: out.txt
229 Entering Extended Passive Mode (|||65503|)
150 Opening ASCII mode data connection for 'out.txt'.
226 Transfer complete.
312128515 bytes sent in 00:02 (116.24 MiB/s)
ftp> passive
Passive mode: off; fallback to active mode: off.
ftp> get in.txt out.txt
local: out.txt remote: in.txt
200 EPRT command successful.
150 Opening ASCII mode data connection for 'in.txt' (306795321 bytes).
226 Transfer complete.
312128515 bytes received in 00:02 (140.56 MiB/s)
ftp> put in.txt out.txt
local: in.txt remote: out.txt
200 EPRT command successful.
150 Opening ASCII mode data connection for 'out.txt'.
226 Transfer complete.
312128515 bytes sent in 00:01 (148.86 MiB/s)
ftp> ^D
221-
Data traffic for this session was 1237847672 bytes in 4 files.
Total traffic for this session was 1237849263 bytes in 4 transfers.
221 Thank you for using the FTP service on localhost.
$
---END TCP_NODELAY log---
From: mlelstv@serpens.de (Michael van Elst)
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60443: ftp ASCII transfers are too slow
Date: Mon, 13 Jul 2026 05:32:32 -0000 (UTC)
gnats-admin@NetBSD.org ("RVP via gnats") writes:
> I don't know how you're getting 35MB/sec w/o any tweaking. Michael, can you try
> with both server and client on localhost like I did?
localhost gets:
ftp> get in.txt
local: in.txt remote: in.txt
229 Entering Extended Passive Mode (|||61368|)
150 Opening ASCII mode data connection for 'in.txt' (306788817 bytes).
226 Transfer complete.
312122680 bytes received in 00:12 (23.66 MiB/s)
> 04:43:22.966644 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 314369:328705, ack 1, win 4096, options [nop,nop,TS val 7 ecr 7], length 14336
+ 200ms
> 04:43:23.166607 IP6 ::1.65424 > ::1.65425: Flags [.], ack 328705, win 4096, options [nop,nop,TS val 7 ecr 7], length 0
+ 0ms
> 04:43:23.166636 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 328705:342017, ack 1, win 4096, options [nop,nop,TS val 7 ecr 7], length 13312
+ 200ms
> 04:43:23.366620 IP6 ::1.65424 > ::1.65425: Flags [.], ack 342017, win 4096, options [nop,nop,TS val 7 ecr 7], length 0
Looks more like the ACKs are delayed and less like Nagle's algorithm. No
idea what is happening.
Here it looks like:
06:42:26.105109 IP6 ::1.55463 > ::1.55464: Flags [SEW], seq 919247764, win 65535, options [mss 33116,nop,wscale 8,sackOK,TS val 1 ecr 0], length 0
06:42:26.105243 IP6 ::1.55464 > ::1.55463: Flags [S.E], seq 929186746, ack 919247765, win 65535, options [mss 33116,nop,wscale 8,sackOK,TS val 1 ecr 1], length 0
06:42:26.105357 IP6 ::1.55463 > ::1.55464: Flags [.], ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.106828 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 1:1025, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 1024
06:42:26.108062 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 1025:17409, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 16384
06:42:26.108202 IP6 ::1.55463 > ::1.55464: Flags [.], ack 17409, win 190, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.108391 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 17409:18433, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 1024
06:42:26.109663 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 18433:34817, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 16384
06:42:26.109774 IP6 ::1.55463 > ::1.55464: Flags [.], ack 34817, win 122, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.109953 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 34817:35841, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 1024
06:42:26.111083 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 35841:52225, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 16384
06:42:26.111189 IP6 ::1.55463 > ::1.55464: Flags [.], ack 52225, win 54, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.111367 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 52225:53249, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 1024
06:42:26.158231 IP6 ::1.55463 > ::1.55464: Flags [.], ack 53249, win 50, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.274512 IP6 ::1.55463 > ::1.55464: Flags [.], ack 53249, win 182, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.274573 IP6 ::1.55464 > ::1.55463: Flags [.], seq 53249:69633, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 16384
06:42:26.274624 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 69633:83969, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 14336
06:42:26.274669 IP6 ::1.55463 > ::1.55464: Flags [.], ack 83969, win 62, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.274734 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 83969:84993, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 1024
06:42:26.275839 IP6 ::1.55463 > ::1.55464: Flags [.], ack 84993, win 190, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.275905 IP6 ::1.55464 > ::1.55463: Flags [.], seq 84993:109569, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 24576
06:42:26.275949 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 109569:129025, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 19456
06:42:26.275988 IP6 ::1.55463 > ::1.55464: Flags [.], ack 129025, win 18, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.276154 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 129025:130049, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 1024
06:42:26.277550 IP6 ::1.55463 > ::1.55464: Flags [.], ack 130049, win 146, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.277616 IP6 ::1.55464 > ::1.55463: Flags [.], seq 130049:163153, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 33104
06:42:26.278857 IP6 ::1.55463 > ::1.55464: Flags [.], ack 163153, win 149, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.278976 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 163153:195585, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 32432
06:42:26.280471 IP6 ::1.55463 > ::1.55464: Flags [.], ack 195585, win 154, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.280526 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 195585:211969, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 16384
06:42:26.281981 IP6 ::1.55463 > ::1.55464: Flags [.], ack 211969, win 222, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.282060 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 211969:218113, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 6144
06:42:26.282665 IP6 ::1.55464 > ::1.55463: Flags [.], seq 218113:251217, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 33104
06:42:26.282715 IP6 ::1.55463 > ::1.55464: Flags [.], ack 251217, win 125, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.282753 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 251217:251905, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 688
06:42:26.283889 IP6 ::1.55463 > ::1.55464: Flags [.], ack 251905, win 254, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.283963 IP6 ::1.55464 > ::1.55463: Flags [.], seq 251905:285009, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 33104
06:42:26.284018 IP6 ::1.55464 > ::1.55463: Flags [P.], seq 285009:316417, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 31408
06:42:26.284067 IP6 ::1.55463 > ::1.55464: Flags [.], ack 316417, win 2, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.285539 IP6 ::1.55463 > ::1.55464: Flags [.], ack 316417, win 134, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.285610 IP6 ::1.55464 > ::1.55463: Flags [.], seq 316417:349521, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 33104
06:42:26.286814 IP6 ::1.55463 > ::1.55464: Flags [.], ack 349521, win 137, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.286884 IP6 ::1.55464 > ::1.55463: Flags [.], seq 349521:382625, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 33104
06:42:26.288301 IP6 ::1.55463 > ::1.55464: Flags [.], ack 382625, win 140, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.288398 IP6 ::1.55464 > ::1.55463: Flags [.], seq 382625:415729, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 33104
06:42:26.289602 IP6 ::1.55463 > ::1.55464: Flags [.], ack 415729, win 142, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.289676 IP6 ::1.55464 > ::1.55463: Flags [.], seq 415729:448833, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 33104
06:42:26.291107 IP6 ::1.55463 > ::1.55464: Flags [.], ack 448833, win 145, options [nop,nop,TS val 1 ecr 1], length 0
06:42:26.291176 IP6 ::1.55464 > ::1.55463: Flags [.], seq 448833:481937, ack 1, win 258, options [nop,nop,TS val 1 ecr 1], length 33104
06:42:26.292396 IP6 ::1.55463 > ::1.55464: Flags [.], ack 481937, win 148, options [nop,nop,TS val 1 ecr 1], length 0
...
06:42:28.345968 IP6 ::1.55464 > ::1.55463: Flags [.], seq 49301969:49335073, ack 1, win 258, options [nop,nop,TS val 5 ecr 5], length 33104
06:42:28.346052 IP6 ::1.55464 > ::1.55463: Flags [.], seq 49335073:49368177, ack 1, win 258, options [nop,nop,TS val 5 ecr 5], length 33104
06:42:28.346108 IP6 ::1.55463 > ::1.55464: Flags [.], ack 49368177, win 41, options [nop,nop,TS val 5 ecr 5], length 0
06:42:28.348542 IP6 ::1.55463 > ::1.55464: Flags [.], ack 49368177, win 301, options [nop,nop,TS val 5 ecr 5], length 0
06:42:28.348625 IP6 ::1.55464 > ::1.55463: Flags [.], seq 49368177:49401281, ack 1, win 258, options [nop,nop,TS val 5 ecr 5], length 33104
06:42:28.348701 IP6 ::1.55464 > ::1.55463: Flags [.], seq 49401281:49434385, ack 1, win 258, options [nop,nop,TS val 5 ecr 5], length 33104
06:42:28.348752 IP6 ::1.55463 > ::1.55464: Flags [.], ack 49434385, win 43, options [nop,nop,TS val 5 ecr 5], length 0
06:42:28.351214 IP6 ::1.55463 > ::1.55464: Flags [.], ack 49434385, win 303, options [nop,nop,TS val 5 ecr 5], length 0
From: RVP <rvp@SDF.ORG>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60443: ftp ASCII transfers are too slow
Date: Tue, 14 Jul 2026 00:23:30 +0000 (UTC)
On Mon, 13 Jul 2026, Michael van Elst via gnats wrote:
> > 04:43:22.966644 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 314369:328705, ack 1, win 4096, options [nop,nop,TS val 7 ecr 7], length 14336
>
> + 200ms
>
> > 04:43:23.166607 IP6 ::1.65424 > ::1.65425: Flags [.], ack 328705, win 4096, options [nop,nop,TS val 7 ecr 7], length 0
>
> + 0ms
>
> > 04:43:23.166636 IP6 ::1.65425 > ::1.65424: Flags [P.], seq 328705:342017, ack 1, win 4096, options [nop,nop,TS val 7 ecr 7], length 13312
>
> + 200ms
>
> > 04:43:23.366620 IP6 ::1.65424 > ::1.65425: Flags [.], ack 342017, win 4096, options [nop,nop,TS val 7 ecr 7], length 0
>
>
> Looks more like the ACKs are delayed and less like Nagle's algorithm. No
> idea what is happening.
>
You're right. Mebbe delayed ACK interacting badly with Nagle. Is there a
TCP_QUICKACK[1] knob in NetBSD?
-RVP
[1]: https://man7.org/linux/man-pages/man7/tcp.7.html
From: mlelstv@serpens.de (Michael van Elst)
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/60443: ftp ASCII transfers are too slow
Date: Tue, 14 Jul 2026 05:34:12 -0000 (UTC)
gnats-admin@NetBSD.org ("RVP via gnats") writes:
> You're right. Mebbe delayed ACK interacting badly with Nagle. Is there a
> TCP_QUICKACK[1] knob in NetBSD?
There is an ack_on_push knob, but that shouldn't be necessary.
You can also change delack_ticks.
N.B. delack_ticks is in clock ticks, so depends on HZ and the default
is 25 (250ms at HZ=100). That knob should be changed to something
independent of HZ.
From: Luke Mewburn <luke@mewburn.net>
To: gnats-bugs@netbsd.org
Cc: gnats-admin@netbsd.org, netbsd-bugs@netbsd.org
Subject: Re: bin/60443: ftp ASCII transfers are too slow
Date: Sun, 19 Jul 2026 18:02:56 +1000
On 26-07-12 08:00, rvp@SDF.ORG via gnats wrote:
| FTP ASCII transfers seem to interact badly with Nagle's algorithm
| because ASCII xfers rely on libc's BUFSIZ (1KB) internal buffer.
|
| If you write 1KB at a time (relatively slowly because you're doing
| getc(3)/putc(3) to locale '\n'), then it looks the 200ms Nagle timeout
| comes into play.
|
| At that's what it seems to me from looking at the tcpdump packet times.
|
| ---START patch ftp(1)---
| diff -urN usr.bin/ftp.orig/ftp.c usr.bin/ftp/ftp.c
| --- usr.bin/ftp.orig/ftp.c 2026-02-07 03:55:18.973125260 +0000
| +++ usr.bin/ftp/ftp.c 2026-02-08 15:51:14.124404272 +0000
| @@ -1728,6 +1728,23 @@
| return (1);
| }
|
| +static FILE *
| +ftp_fdopen(int fd, const char *lmode)
| +{
| + enum { BSIZ = XFERBUFMIN * 4 }; /* 4K (any >MTU) */
I think we could use a similar buffer sizing logic to what I
implemented in ftp.c 1.181 on 2026/02/07 in recvrequest():
if (rcvbuf_size == 0)
bufsize = XFERBUFMAX;
else
bufsize = MAX(XFERBUFMIN, MIN(rcvbuf_size, XFERBUFMAX));
(maybe this logic could be centralized for easier reuse).
Unless this will cause issues on low memory systems with large
stdio buffer and separate binary mode read buffer?
| + FILE *fp;
| + void* buf;
| +
| + if ((fp = fdopen(fd, lmode)) == NULL)
| + return NULL;
| + if ((buf = ftp_malloc(BSIZ)) == NULL) {
| + fclose(fp);
| + return NULL;
| + }
| + (void)setvbuf(fp, buf, _IOFBF, BSIZ);
Doesn't this leak "buf" because we've allocated it?
What if we just call setvbuf() with buf==NULL which
should let the stdio cleanup when the FILE is closed?
I've done a bit of reading into different setvbuf()
man pages (POSIX, Linux, NetBSD, macOS, cppreference), and it
seems that all support auto-allocating if buf==NULL and freeing
on close.
POSIX setvbuf(3) states (https://pubs.opengroup.org/onlinepubs/9699919799/functions/setvbuf.html):
If buf is not a null pointer, the array it points to may be used
instead of a buffer allocated by setvbuf() and the argument size
specifies the size of the array; otherwise, size may determine
the size of a buffer allocated by the setvbuf() function.
Linux setvbuf(3) states:
If the argument buf is NULL, only the mode is affected;
a new buffer will be allocated on the next read or write
operation.
However, NetBSD setvbuf(3) states:
(If the size argument is not zero but buf is NULL,
a buffer of the given size will be allocated immediately,
and released on close. This is an extension to ANSI C;
portable code should use a size of 0 with any NULL buffer.)
macOS has a variation of this - understandable since both are 4.xBSD
derived man pages.
cppreference.com (https://en.cppreference.com/c/io/setvbuf)
If buffer is a null pointer, resizes the internal buffer to
size.
regards,
Luke.
(Contact us)
$NetBSD: query-full-pr,v 1.51 2026/08/10 02:28:17 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.