NetBSD Problem Report #58874
From www@netbsd.org Thu Dec 5 00:25:25 2024
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)
client-signature RSA-PSS (2048 bits))
(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id 9DB161A9238
for <gnats-bugs@gnats.NetBSD.org>; Thu, 5 Dec 2024 00:25:25 +0000 (UTC)
Message-Id: <20241205002524.762C61A923B@mollari.NetBSD.org>
Date: Thu, 5 Dec 2024 00:25:24 +0000 (UTC)
From: campbell+netbsd@mumble.net
Reply-To: campbell+netbsd@mumble.net
To: gnats-bugs@NetBSD.org
Subject: nonblocking connect() and getsockname() error conditions
X-Send-Pr-Version: www-1.0
>Number: 58874
>Notify-List: kim
>Category: kern
>Synopsis: nonblocking connect() and getsockname() error conditions
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Dec 05 00:30:01 +0000 2024
>Last-Modified: Sun Mar 16 07:16:55 +0000 2025
>Originator: Taylor R Campbell
>Release: 10
>Organization:
The NetBSD EINPROGRESS
>Environment:
>Description:
NetBSD and Linux disagree on some error conditions of nonblocking
connect() and getsockname() when the connection is refused,
illustrated by the following program.
Maybe both are sensible and compatible with POSIX -- I don't know, I
haven't assessed; I just stumbled upon the difference while running
git-cinnabar tests:
https://github.com/glandium/git-cinnabar/issues/340
So I'm filing this PR to make a record of the difference and any
determination about it.
#include <sys/socket.h>
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
main(int argc, char **argv)
{
struct addrinfo *ai0, *ai, hints;
int error;
if (argc != 3)
errx(1, "Usage: %s <host> <service>", argv[0]);
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(argv[1], argv[2], &hints, &ai0);
if (error)
errx(1, "getaddrinfo: %s", gai_strerror(error));
for (ai = ai0; ai != NULL; ai = ai->ai_next) {
int fd;
struct sockaddr_storage ss;
socklen_t namelen;
socklen_t optlen;
socklen_t i;
fd = socket(ai->ai_family, ai->ai_socktype|SOCK_NONBLOCK,
ai->ai_protocol);
if (fd == -1) {
warn("socket");
continue;
}
if (connect(fd, ai->ai_addr, ai->ai_addrlen) != -1) {
warnx("connect succeeded");
(void)close(fd);
continue;
}
if (errno != EINPROGRESS)
err(1, "connect failed unexpectedly");
warn("first connect");
if (connect(fd, ai->ai_addr, ai->ai_addrlen) == -1)
warn("second connect");
else
warnx("second connect succeeded!");
if (getsockname(fd, (struct sockaddr *)&ss, &namelen) == -1) {
warn("getsockname");
} else {
for (i = 0; i < namelen; i++) {
fprintf(stderr, "%02hhx",
((const char *)&ss)[i]);
}
fprintf(stderr, "\n");
}
optlen = sizeof(error);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &optlen) ==
-1)
err(1, "getsockopt(SO_ERROR)");
errno = error;
warn("connect SO_ERROR");
if (connect(fd, ai->ai_addr, ai->ai_addrlen) == -1)
warn("third connect");
else
warnx("third connect succeeded!");
return 0;
}
errx(1, "no addresses");
}
>How-To-Repeat:
linux$ ./sn localhost 12345
sn: first connect: Operation now in progress
sn: second connect: Connection refused
00000000000000000000000000000000000000000000000000000000
sn: connect SO_ERROR: Success
sn: third connect: Operation now in progress
netbsd$ ./sn localhost 12345
sn: first connect: Operation now in progress
sn: second connect: Invalid argument
sn: getsockname: Invalid argument
sn: connect SO_ERROR: Connection refused
sn: third connect: Invalid argument
>Fix:
1. determine whether there is a problem here
2. maybe make a change
>Release-Note:
>Audit-Trail:
From: Simon Burge <simonb@NetBSD.org>
To: gnats-bugs@netbsd.org
Cc: kern-bug-people@netbsd.org, gnats-admin@netbsd.org,
netbsd-bugs@netbsd.org
Subject: Re: kern/58874: nonblocking connect() and getsockname() error conditions
Date: Sun, 15 Dec 2024 16:27:26 +1100
campbell+netbsd@mumble.net wrote:
> Maybe both are sensible and compatible with POSIX -- I don't know, I
> haven't assessed; I just stumbled upon the difference while running
> git-cinnabar tests:
>
> https://github.com/glandium/git-cinnabar/issues/340
>
> So I'm filing this PR to make a record of the difference and any
> determination about it.
>
> [ test program deleted ]
On FreeBSD 13.3:
freebsd$ ./sn localhost 12345
sn: first connect: Operation now in progress
sn: second connect: Connection refused
sn: connect SO_ERROR: No error: 0
sn: third connect: Connection refused
Cheers,
Simon.
From: Christoph Badura <bad@bsd.de>
To: gnats-bugs@NetBSD.org
Cc:
Subject: Re: kern/58874: nonblocking connect() and getsockname() error
conditions
Date: Sun, 15 Dec 2024 12:10:59 +0100
macOS doesn't have SOCK_NONBLOCK, so:
--- sn.c,0 2024-12-15 11:39:56
+++ sn.c 2024-12-15 11:59:50
@@ -2,6 +2,7 @@
#include <err.h>
#include <errno.h>
+#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
@@ -30,12 +31,14 @@
socklen_t optlen;
socklen_t i;
- fd = socket(ai->ai_family, ai->ai_socktype|SOCK_NONBLOCK,
+ fd = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
if (fd == -1) {
warn("socket");
continue;
}
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
+ err(1, "fcntl can't F_SETFL O_NONBLOCK");
if (connect(fd, ai->ai_addr, ai->ai_addrlen) != -1) {
warnx("connect succeeded");
(void)close(fd);
output (macOS 14.7.1, amd64):
Script started on Sun Dec 15 12:03:09 2024
Command: ./sn localhost 12345
sn: first connect: Operation now in progress
sn: second connect: Connection refused
1c1ef713000000000000000000000000000000000000000100000000
sn: connect SO_ERROR: Undefined error: 0
sn: third connect: Invalid argument
Command exit status: 0
Script done on Sun Dec 15 12:03:09 2024
--chris
From: Valery Ushakov <uwe@stderr.spb.ru>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: kern/58874: nonblocking connect() and getsockname() error
conditions
Date: Sun, 15 Dec 2024 19:04:31 +0300
Solaris 11.3 (with the fnctl patch)
$ ./sn localhost 12345
sn: first connect: Operation now in progress
sn: second connect: Connection refused
1a00000000000000000000000000000000000000000000000000000000000000
sn: connect SO_ERROR: Error 0
sn: third connect: Operation now in progress
-uwe
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.49 2026/05/14 01:52:41 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.