* [PATCH] net: unix: clarify BSD behavior comment in unix_release_sock() [not found] <20251017-fix-fix-me-v1-1-8c509d7122ed.ref@yahoo.com> @ 2025-10-17 13:30 ` Sunday Adelodun 2025-10-18 23:52 ` Kuniyuki Iwashima 0 siblings, 1 reply; 3+ messages in thread From: Sunday Adelodun @ 2025-10-17 13:30 UTC (permalink / raw) To: Kuniyuki Iwashima, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman Cc: netdev, linux-kernel, skhan, Sunday Adelodun The long-standing comment in unix_release_sock() mentioned a "FIXME" about BSD sending ECONNRESET to connected sockets upon closure, while Linux waits for the last reference. This behavior has existed since early UNIX socket implementations and is intentional. Update the comment to clarify that this is a deliberate design difference, not a pending fix, and remove the outdated FIXME marker. Signed-off-by: Sunday Adelodun <adelodunolaoluwa@yahoo.com> --- net/unix/af_unix.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 768098dec231..c21230a69f42 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -734,14 +734,13 @@ static void unix_release_sock(struct sock *sk, int embrion) /* ---- Socket is dead now and most probably destroyed ---- */ /* - * Fixme: BSD difference: In BSD all sockets connected to us get - * ECONNRESET and we die on the spot. In Linux we behave - * like files and pipes do and wait for the last - * dereference. + * Note: BSD sends ECONNREST to all sockets connected to a closing peer + * and terminates immediately. Linux, however, intentionally behaves more + * like pipes - waiting for the final dereference before destruction. * - * Can't we simply set sock->err? - * - * What the above comment does talk about? --ANK(980817) + * This behaviour is by design and aligns with Linux's file semantics. + * Historical note: this difference from BSD has been present since the + * early UNIX socket implementation and is not considered a bug. */ if (READ_ONCE(unix_tot_inflight)) --- base-commit: 7ea30958b3054f5e488fa0b33c352723f7ab3a2a change-id: 20251017-fix-fix-me-59b369ffcfb5 Best regards, -- Sunday Adelodun <adelodunolaoluwa@yahoo.com> ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] net: unix: clarify BSD behavior comment in unix_release_sock() 2025-10-17 13:30 ` [PATCH] net: unix: clarify BSD behavior comment in unix_release_sock() Sunday Adelodun @ 2025-10-18 23:52 ` Kuniyuki Iwashima 2025-10-21 19:06 ` Sunday Adelodun 0 siblings, 1 reply; 3+ messages in thread From: Kuniyuki Iwashima @ 2025-10-18 23:52 UTC (permalink / raw) To: adelodunolaoluwa Cc: davem, edumazet, horms, kuba, kuniyu, linux-kernel, netdev, pabeni, skhan From: Sunday Adelodun <adelodunolaoluwa@yahoo.com> Date: Fri, 17 Oct 2025 14:30:45 +0100 > The long-standing comment in unix_release_sock() mentioned a "FIXME" about > BSD sending ECONNRESET to connected sockets upon closure, while Linux waits > for the last reference. This behavior has existed since early UNIX socket > implementations and is intentional. > > Update the comment to clarify that this is a deliberate design difference, > not a pending fix, and remove the outdated FIXME marker. > > Signed-off-by: Sunday Adelodun <adelodunolaoluwa@yahoo.com> > --- > net/unix/af_unix.c | 13 ++++++------- > 1 file changed, 6 insertions(+), 7 deletions(-) > > diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c > index 768098dec231..c21230a69f42 100644 > --- a/net/unix/af_unix.c > +++ b/net/unix/af_unix.c > @@ -734,14 +734,13 @@ static void unix_release_sock(struct sock *sk, int embrion) > /* ---- Socket is dead now and most probably destroyed ---- */ > > /* > - * Fixme: BSD difference: In BSD all sockets connected to us get > - * ECONNRESET and we die on the spot. In Linux we behave > - * like files and pipes do and wait for the last > - * dereference. > + * Note: BSD sends ECONNREST to all sockets connected to a closing peer > + * and terminates immediately. I ran a script below on Mac (I hope the behvaviour does not differ from FreeBSD), and I only see ECONNRESET on SOCK_DGRAM test case. Even after close()ing a SOCK_STREAM socket, its peer can read 0, not ECONNRESET. So, the comment looks outdated. ---8<--- $ python3 a.py test 1 b'hello' b'' test 2 b'' b'' test 3 [Errno 54] Connection reset by peer ---8<--- > Linux, however, intentionally behaves more > + * like pipes - waiting for the final dereference before destruction. Note that Linux also sets ECONNRESET if the close()d socket has unread data or is not yet accept()ed. You can find this a few lines above of the diff. ---8<--- $ python3 a.py test 1 b'hello' b'' test 2 [Errno 104] Connection reset by peer test 3 [Errno 11] Resource temporarily unavailable ---8<--- > * > - * Can't we simply set sock->err? > - * > - * What the above comment does talk about? --ANK(980817) > + * This behaviour is by design and aligns with Linux's file semantics. > + * Historical note: this difference from BSD has been present since the > + * early UNIX socket implementation and is not considered a bug. > */ So, I'd remove the entire comment, and if needed, add a selftest and update man page. Thanks! ---8<--- import os from socket import * def test1(): print("test 1") server = socket(AF_UNIX, SOCK_STREAM) server.bind(b'test') server.listen() client = socket(AF_UNIX, SOCK_STREAM) client.connect(server.getsockname()) child, _ = server.accept() child.send(b'hello') child.close() try: client.setblocking(False) print(client.recv(20)) print(client.recv(20)) except Exception as e: print(e) client.close() server.close() os.remove('test') def test2(): print("test 2") server = socket(AF_UNIX, SOCK_STREAM) server.bind(b'test') server.listen() client = socket(AF_UNIX, SOCK_STREAM) client.connect(server.getsockname()) child, _ = server.accept() client.send(b'hello') child.close() try: client.setblocking(False) print(client.recv(20)) print(client.recv(20)) except Exception as e: print(e) client.close() server.close() os.remove('test') def test3(): print("test 3") server = socket(AF_UNIX, SOCK_DGRAM) server.bind(b'test') client = socket(AF_UNIX, SOCK_DGRAM) client.connect(server.getsockname()) client.send(b'hello') server.close() try: client.setblocking(False) print(client.recv(20)) print(client.recv(20)) except Exception as e: print(e) client.close() os.remove('test') test1() test2() test3() ---8<--- ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] net: unix: clarify BSD behavior comment in unix_release_sock() 2025-10-18 23:52 ` Kuniyuki Iwashima @ 2025-10-21 19:06 ` Sunday Adelodun 0 siblings, 0 replies; 3+ messages in thread From: Sunday Adelodun @ 2025-10-21 19:06 UTC (permalink / raw) To: Kuniyuki Iwashima Cc: davem, edumazet, horms, kuba, linux-kernel, netdev, pabeni, skhan, david.hunter.linux On 10/19/25 00:52, Kuniyuki Iwashima wrote: > From: Sunday Adelodun <adelodunolaoluwa@yahoo.com> > Date: Fri, 17 Oct 2025 14:30:45 +0100 >> The long-standing comment in unix_release_sock() mentioned a "FIXME" about >> BSD sending ECONNRESET to connected sockets upon closure, while Linux waits >> for the last reference. This behavior has existed since early UNIX socket >> implementations and is intentional. >> >> Update the comment to clarify that this is a deliberate design difference, >> not a pending fix, and remove the outdated FIXME marker. >> >> Signed-off-by: Sunday Adelodun <adelodunolaoluwa@yahoo.com> >> --- >> net/unix/af_unix.c | 13 ++++++------- >> 1 file changed, 6 insertions(+), 7 deletions(-) >> >> diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c >> index 768098dec231..c21230a69f42 100644 >> --- a/net/unix/af_unix.c >> +++ b/net/unix/af_unix.c >> @@ -734,14 +734,13 @@ static void unix_release_sock(struct sock *sk, int embrion) >> /* ---- Socket is dead now and most probably destroyed ---- */ >> >> /* >> - * Fixme: BSD difference: In BSD all sockets connected to us get >> - * ECONNRESET and we die on the spot. In Linux we behave >> - * like files and pipes do and wait for the last >> - * dereference. >> + * Note: BSD sends ECONNREST to all sockets connected to a closing peer >> + * and terminates immediately. > I ran a script below on Mac (I hope the behvaviour does > not differ from FreeBSD), and I only see ECONNRESET on > SOCK_DGRAM test case. > > Even after close()ing a SOCK_STREAM socket, its peer can > read 0, not ECONNRESET. > > So, the comment looks outdated. > > ---8<--- > $ python3 a.py > test 1 > b'hello' > b'' > test 2 > b'' > b'' > test 3 > [Errno 54] Connection reset by peer > ---8<--- > > >> Linux, however, intentionally behaves more >> + * like pipes - waiting for the final dereference before destruction. > Note that Linux also sets ECONNRESET if the close()d socket > has unread data or is not yet accept()ed. You can find this > a few lines above of the diff. > > ---8<--- > $ python3 a.py > test 1 > b'hello' > b'' > test 2 > [Errno 104] Connection reset by peer > test 3 > [Errno 11] Resource temporarily unavailable > ---8<--- > > >> * >> - * Can't we simply set sock->err? >> - * >> - * What the above comment does talk about? --ANK(980817) >> + * This behaviour is by design and aligns with Linux's file semantics. >> + * Historical note: this difference from BSD has been present since the >> + * early UNIX socket implementation and is not considered a bug. >> */ > So, I'd remove the entire comment, and if needed, add a > selftest and update man page. > > Thanks! > > > ---8<--- > import os > from socket import * > > > def test1(): > print("test 1") > server = socket(AF_UNIX, SOCK_STREAM) > server.bind(b'test') > server.listen() > > client = socket(AF_UNIX, SOCK_STREAM) > client.connect(server.getsockname()) > > child, _ = server.accept() > > child.send(b'hello') > child.close() > > try: > client.setblocking(False) > print(client.recv(20)) > print(client.recv(20)) > except Exception as e: > print(e) > > client.close() > server.close() > os.remove('test') > > > def test2(): > print("test 2") > server = socket(AF_UNIX, SOCK_STREAM) > server.bind(b'test') > server.listen() > > client = socket(AF_UNIX, SOCK_STREAM) > client.connect(server.getsockname()) > > child, _ = server.accept() > > client.send(b'hello') > child.close() > > try: > client.setblocking(False) > print(client.recv(20)) > print(client.recv(20)) > except Exception as e: > print(e) > > client.close() > server.close() > os.remove('test') > > > def test3(): > print("test 3") > server = socket(AF_UNIX, SOCK_DGRAM) > server.bind(b'test') > > client = socket(AF_UNIX, SOCK_DGRAM) > client.connect(server.getsockname()) > > client.send(b'hello') > server.close() > > try: > client.setblocking(False) > print(client.recv(20)) > print(client.recv(20)) > except Exception as e: > print(e) > > client.close() > os.remove('test') > > > test1() > test2() > test3() > ---8<--- Thanks Kuniyuki for the detailed explanation and example script. I'll go ahead and send a v2 that removes the entire comment as you suggested. After that, I’ll work on a follow-up patch to add a selftest for this behavior. Thanks again! Sunday ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-10-21 19:27 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20251017-fix-fix-me-v1-1-8c509d7122ed.ref@yahoo.com>
2025-10-17 13:30 ` [PATCH] net: unix: clarify BSD behavior comment in unix_release_sock() Sunday Adelodun
2025-10-18 23:52 ` Kuniyuki Iwashima
2025-10-21 19:06 ` Sunday Adelodun
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®