* [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®