* [ruby-core:109961] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections
@ 2022-09-20 13:52 byroot (Jean Boussier)
2022-09-20 14:13 ` [ruby-core:109962] " byroot (Jean Boussier)
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: byroot (Jean Boussier) @ 2022-09-20 13:52 UTC (permalink / raw)
To: ruby-core
Issue #19012 has been reported by byroot (Jean Boussier).
----------------------------------------
Bug #19012: BasicSocket#recv* methods return an empty packet instead of nil on closed connections
https://bugs.ruby-lang.org/issues/19012
* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
`man recvmsg(2)` states:
> Return Value
> These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an orderly shutdown.
But somehow the entire `receiv` family of methods in Ruby seem to interpret `0` as empty string instead of "EOF".
```ruby
require 'socket'
puts "=== pipes ==="
r, w = IO.pipe
r.read_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
puts "=== sockets ===="
r, w = UNIXSocket.socketpair
r.read_nonblock(1, exception: false) # => :wait_readable
r.recvmsg_nonblock(1, exception: false) # => :wait_readable
r.recv_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
r.recvmsg_nonblock(1, exception: false) # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 128]]
r.recvmsg # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 0]]
r.recv_nonblock(1, exception: false) # => ""
```
### Expected behavior
I would expect `recvmsg_nonblock`, `recvmsg`, `recv_nonblock` and `recv` to return `nil` when the connection is closed.
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 8+ messages in thread
* [ruby-core:109962] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections
2022-09-20 13:52 [ruby-core:109961] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections byroot (Jean Boussier)
@ 2022-09-20 14:13 ` byroot (Jean Boussier)
2022-09-21 8:02 ` [ruby-core:109972] " byroot (Jean Boussier)
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: byroot (Jean Boussier) @ 2022-09-20 14:13 UTC (permalink / raw)
To: ruby-core
Issue #19012 has been updated by byroot (Jean Boussier).
I opened a PoC patch for it: https://github.com/ruby/ruby/pull/6407
----------------------------------------
Bug #19012: BasicSocket#recv* methods return an empty packet instead of nil on closed connections
https://bugs.ruby-lang.org/issues/19012#change-99212
* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
`man recvmsg(2)` states:
> Return Value
> These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an orderly shutdown.
But somehow the entire `receiv` family of methods in Ruby seem to interpret `0` as empty string instead of "EOF".
```ruby
require 'socket'
puts "=== pipes ==="
r, w = IO.pipe
r.read_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
puts "=== sockets ===="
r, w = UNIXSocket.socketpair
r.read_nonblock(1, exception: false) # => :wait_readable
r.recvmsg_nonblock(1, exception: false) # => :wait_readable
r.recv_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
r.recvmsg_nonblock(1, exception: false) # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 128]]
r.recvmsg # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 0]]
r.recv_nonblock(1, exception: false) # => ""
```
### Expected behavior
I would expect `recvmsg_nonblock`, `recvmsg`, `recv_nonblock` and `recv` to return `nil` when the connection is closed.
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 8+ messages in thread
* [ruby-core:109972] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections
2022-09-20 13:52 [ruby-core:109961] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections byroot (Jean Boussier)
2022-09-20 14:13 ` [ruby-core:109962] " byroot (Jean Boussier)
@ 2022-09-21 8:02 ` byroot (Jean Boussier)
2022-12-02 2:15 ` [ruby-core:111139] " mame (Yusuke Endoh)
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: byroot (Jean Boussier) @ 2022-09-21 8:02 UTC (permalink / raw)
To: ruby-core
Issue #19012 has been updated by byroot (Jean Boussier).
@akr pointed on the PR that this behavior might be desirable for "connection-less" sockets such as `DGRAM`.
That said I think we should try to distinguish between "nothing was received" and "we received an empty packet".
I'm not quite familiar enough with `recv` (yet) to know whether it's possible to make the difference though. I'll try to research this more when I have a bit of time.
----------------------------------------
Bug #19012: BasicSocket#recv* methods return an empty packet instead of nil on closed connections
https://bugs.ruby-lang.org/issues/19012#change-99222
* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
`man recvmsg(2)` states:
> Return Value
> These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an orderly shutdown.
But somehow the entire `receiv` family of methods in Ruby seem to interpret `0` as empty string instead of "EOF".
```ruby
require 'socket'
puts "=== pipes ==="
r, w = IO.pipe
r.read_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
puts "=== sockets ===="
r, w = UNIXSocket.socketpair
r.read_nonblock(1, exception: false) # => :wait_readable
r.recvmsg_nonblock(1, exception: false) # => :wait_readable
r.recv_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
r.recvmsg_nonblock(1, exception: false) # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 128]]
r.recvmsg # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 0]]
r.recv_nonblock(1, exception: false) # => ""
```
### Expected behavior
I would expect `recvmsg_nonblock`, `recvmsg`, `recv_nonblock` and `recv` to return `nil` when the connection is closed.
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 8+ messages in thread
* [ruby-core:111139] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections
2022-09-20 13:52 [ruby-core:109961] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections byroot (Jean Boussier)
2022-09-20 14:13 ` [ruby-core:109962] " byroot (Jean Boussier)
2022-09-21 8:02 ` [ruby-core:109972] " byroot (Jean Boussier)
@ 2022-12-02 2:15 ` mame (Yusuke Endoh)
2022-12-02 11:46 ` [ruby-core:111152] " byroot (Jean Boussier)
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: mame (Yusuke Endoh) @ 2022-12-02 2:15 UTC (permalink / raw)
To: ruby-core
Issue #19012 has been updated by mame (Yusuke Endoh).
This is what @akr said at the dev meeting. (My understanding)
> The proposed behavior might be possible for stream. On the other hand, for datagram, the current behavior is better. I am not sure if there is a portable way to determine if the file descriptor behind an IO object is stream or datagram.
----------------------------------------
Bug #19012: BasicSocket#recv* methods return an empty packet instead of nil on closed connections
https://bugs.ruby-lang.org/issues/19012#change-100419
* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
`man recvmsg(2)` states:
> Return Value
> These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an orderly shutdown.
But somehow the entire `receiv` family of methods in Ruby seem to interpret `0` as empty string instead of "EOF".
```ruby
require 'socket'
puts "=== pipes ==="
r, w = IO.pipe
r.read_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
puts "=== sockets ===="
r, w = UNIXSocket.socketpair
r.read_nonblock(1, exception: false) # => :wait_readable
r.recvmsg_nonblock(1, exception: false) # => :wait_readable
r.recv_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
r.recvmsg_nonblock(1, exception: false) # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 128]]
r.recvmsg # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 0]]
r.recv_nonblock(1, exception: false) # => ""
```
### Expected behavior
I would expect `recvmsg_nonblock`, `recvmsg`, `recv_nonblock` and `recv` to return `nil` when the connection is closed.
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 8+ messages in thread
* [ruby-core:111152] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections
2022-09-20 13:52 [ruby-core:109961] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections byroot (Jean Boussier)
` (2 preceding siblings ...)
2022-12-02 2:15 ` [ruby-core:111139] " mame (Yusuke Endoh)
@ 2022-12-02 11:46 ` byroot (Jean Boussier)
2022-12-02 11:52 ` [ruby-core:111153] " byroot (Jean Boussier)
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: byroot (Jean Boussier) @ 2022-12-02 11:46 UTC (permalink / raw)
To: ruby-core
Issue #19012 has been updated by byroot (Jean Boussier).
> I am not sure if there is a portable way to determine if the file descriptor behind an IO object is stream or datagram.
Yeah, me neither. I'll try to dig more.
----------------------------------------
Bug #19012: BasicSocket#recv* methods return an empty packet instead of nil on closed connections
https://bugs.ruby-lang.org/issues/19012#change-100436
* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
`man recvmsg(2)` states:
> Return Value
> These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an orderly shutdown.
But somehow the entire `receiv` family of methods in Ruby seem to interpret `0` as empty string instead of "EOF".
```ruby
require 'socket'
puts "=== pipes ==="
r, w = IO.pipe
r.read_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
puts "=== sockets ===="
r, w = UNIXSocket.socketpair
r.read_nonblock(1, exception: false) # => :wait_readable
r.recvmsg_nonblock(1, exception: false) # => :wait_readable
r.recv_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
r.recvmsg_nonblock(1, exception: false) # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 128]]
r.recvmsg # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 0]]
r.recv_nonblock(1, exception: false) # => ""
```
### Expected behavior
I would expect `recvmsg_nonblock`, `recvmsg`, `recv_nonblock` and `recv` to return `nil` when the connection is closed.
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 8+ messages in thread
* [ruby-core:111153] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections
2022-09-20 13:52 [ruby-core:109961] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections byroot (Jean Boussier)
` (3 preceding siblings ...)
2022-12-02 11:46 ` [ruby-core:111152] " byroot (Jean Boussier)
@ 2022-12-02 11:52 ` byroot (Jean Boussier)
2022-12-07 7:56 ` [ruby-core:111227] " byroot (Jean Boussier)
2023-12-17 19:52 ` [ruby-core:115768] " zverok (Victor Shepelev) via ruby-core
6 siblings, 0 replies; 8+ messages in thread
From: byroot (Jean Boussier) @ 2022-12-02 11:52 UTC (permalink / raw)
To: ruby-core
Issue #19012 has been updated by byroot (Jean Boussier).
Apparently we can get this via `getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &length);`, the question being how portable it is.
----------------------------------------
Bug #19012: BasicSocket#recv* methods return an empty packet instead of nil on closed connections
https://bugs.ruby-lang.org/issues/19012#change-100437
* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
`man recvmsg(2)` states:
> Return Value
> These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an orderly shutdown.
But somehow the entire `receiv` family of methods in Ruby seem to interpret `0` as empty string instead of "EOF".
```ruby
require 'socket'
puts "=== pipes ==="
r, w = IO.pipe
r.read_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
puts "=== sockets ===="
r, w = UNIXSocket.socketpair
r.read_nonblock(1, exception: false) # => :wait_readable
r.recvmsg_nonblock(1, exception: false) # => :wait_readable
r.recv_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
r.recvmsg_nonblock(1, exception: false) # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 128]]
r.recvmsg # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 0]]
r.recv_nonblock(1, exception: false) # => ""
```
### Expected behavior
I would expect `recvmsg_nonblock`, `recvmsg`, `recv_nonblock` and `recv` to return `nil` when the connection is closed.
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 8+ messages in thread
* [ruby-core:111227] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections
2022-09-20 13:52 [ruby-core:109961] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections byroot (Jean Boussier)
` (4 preceding siblings ...)
2022-12-02 11:52 ` [ruby-core:111153] " byroot (Jean Boussier)
@ 2022-12-07 7:56 ` byroot (Jean Boussier)
2023-12-17 19:52 ` [ruby-core:115768] " zverok (Victor Shepelev) via ruby-core
6 siblings, 0 replies; 8+ messages in thread
From: byroot (Jean Boussier) @ 2022-12-07 7:56 UTC (permalink / raw)
To: ruby-core
Issue #19012 has been updated by byroot (Jean Boussier).
I was able to implement the desired behavior in https://github.com/ruby/ruby/pull/6407
----------------------------------------
Bug #19012: BasicSocket#recv* methods return an empty packet instead of nil on closed connections
https://bugs.ruby-lang.org/issues/19012#change-100516
* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
`man recvmsg(2)` states:
> Return Value
> These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an orderly shutdown.
But somehow the entire `receiv` family of methods in Ruby seem to interpret `0` as empty string instead of "EOF".
```ruby
require 'socket'
puts "=== pipes ==="
r, w = IO.pipe
r.read_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
puts "=== sockets ===="
r, w = UNIXSocket.socketpair
r.read_nonblock(1, exception: false) # => :wait_readable
r.recvmsg_nonblock(1, exception: false) # => :wait_readable
r.recv_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
r.recvmsg_nonblock(1, exception: false) # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 128]]
r.recvmsg # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 0]]
r.recv_nonblock(1, exception: false) # => ""
```
### Expected behavior
I would expect `recvmsg_nonblock`, `recvmsg`, `recv_nonblock` and `recv` to return `nil` when the connection is closed.
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 8+ messages in thread
* [ruby-core:115768] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections
2022-09-20 13:52 [ruby-core:109961] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections byroot (Jean Boussier)
` (5 preceding siblings ...)
2022-12-07 7:56 ` [ruby-core:111227] " byroot (Jean Boussier)
@ 2023-12-17 19:52 ` zverok (Victor Shepelev) via ruby-core
6 siblings, 0 replies; 8+ messages in thread
From: zverok (Victor Shepelev) via ruby-core @ 2023-12-17 19:52 UTC (permalink / raw)
To: ruby-core; +Cc: zverok (Victor Shepelev)
Issue #19012 has been updated by zverok (Victor Shepelev).
Should the docs for [BasicSocket#recv_nonblock](https://docs.ruby-lang.org/en/master/BasicSocket.html#method-i-recv_nonblock) be updated? Now they state
> When recvfrom(2) returns 0, Socket#recv_nonblock returns an empty string as data. The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc.
I am not sure whether the change affects all the cases (this thing about datagrams got me confused).
Other affected methods don't have a similar clause, but this one seems to directly contradict the implemented behavior now.
----------------------------------------
Bug #19012: BasicSocket#recv* methods return an empty packet instead of nil on closed connections
https://bugs.ruby-lang.org/issues/19012#change-105705
* Author: byroot (Jean Boussier)
* Status: Closed
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
`man recvmsg(2)` states:
> Return Value
> These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an orderly shutdown.
But somehow the entire `receiv` family of methods in Ruby seem to interpret `0` as empty string instead of "EOF".
```ruby
require 'socket'
puts "=== pipes ==="
r, w = IO.pipe
r.read_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
puts "=== sockets ===="
r, w = UNIXSocket.socketpair
r.read_nonblock(1, exception: false) # => :wait_readable
r.recvmsg_nonblock(1, exception: false) # => :wait_readable
r.recv_nonblock(1, exception: false) # => :wait_readable
w.close
r.read_nonblock(1, exception: false) # => nil (EOF)
r.recvmsg_nonblock(1, exception: false) # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 128]]
r.recvmsg # => ["", #<Addrinfo: empty-sockaddr SOCK_STREAM>, 0]]
r.recv_nonblock(1, exception: false) # => ""
```
### Expected behavior
I would expect `recvmsg_nonblock`, `recvmsg`, `recv_nonblock` and `recv` to return `nil` when the connection is closed.
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2023-12-17 19:52 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-20 13:52 [ruby-core:109961] [Ruby master Bug#19012] BasicSocket#recv* methods return an empty packet instead of nil on closed connections byroot (Jean Boussier)
2022-09-20 14:13 ` [ruby-core:109962] " byroot (Jean Boussier)
2022-09-21 8:02 ` [ruby-core:109972] " byroot (Jean Boussier)
2022-12-02 2:15 ` [ruby-core:111139] " mame (Yusuke Endoh)
2022-12-02 11:46 ` [ruby-core:111152] " byroot (Jean Boussier)
2022-12-02 11:52 ` [ruby-core:111153] " byroot (Jean Boussier)
2022-12-07 7:56 ` [ruby-core:111227] " byroot (Jean Boussier)
2023-12-17 19:52 ` [ruby-core:115768] " zverok (Victor Shepelev) via ruby-core
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).