Project

General

Profile

Feature #13362

[PATCH] socket: avoid fcntl for read/write_nonblock on Linux

Added by normalperson (Eric Wong) about 2 years ago. Updated about 2 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:80302]

Description

On platforms where MSG_DONTWAIT works reliably on all sockets
(so far, I know of Linux), we can avoid fcntl syscalls and
implement IO#write_nonblock and IO#read_nonblock in terms of the
socket-specific send and recv family of syscalls.

This avoids side effects on the socket, and also encourages
generic code to be written in cases where IO wrappers like
OpenSSL::SSL::SSLSocket are used.

I could've sworn I sent something like this years ago, but
maybe I'm confusing it with kgio or socket_dontwait.


Files

Associated revisions

Revision c32fc82d
Added by normal about 2 years ago

socket: avoid fcntl for read/write_nonblock on Linux

On platforms where MSG_DONTWAIT works reliably on all sockets
(so far, I know of Linux), we can avoid fcntl syscalls and
implement IO#write_nonblock and IO#read_nonblock in terms of the
socket-specific send and recv family of syscalls.

This avoids side effects on the socket, and also encourages
generic code to be written in cases where IO wrappers like
OpenSSL::SSL::SSLSocket are used.

Perhaps in the future, side-effect-free non-blocking I/O can
be standard on all files and OSes: https://cr.yp.to/unix/nonblock.html

  • ext/socket/lib/socket.rb (read_nonblock, write_nonblock): Linux-specific wrapper without side effects [ruby-core:80780] [Feature #13362]
  • test/socket/test_basicsocket.rb (test_read_write_nonblock): new test

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58400 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 58400
Added by normalperson (Eric Wong) about 2 years ago

socket: avoid fcntl for read/write_nonblock on Linux

On platforms where MSG_DONTWAIT works reliably on all sockets
(so far, I know of Linux), we can avoid fcntl syscalls and
implement IO#write_nonblock and IO#read_nonblock in terms of the
socket-specific send and recv family of syscalls.

This avoids side effects on the socket, and also encourages
generic code to be written in cases where IO wrappers like
OpenSSL::SSL::SSLSocket are used.

Perhaps in the future, side-effect-free non-blocking I/O can
be standard on all files and OSes: https://cr.yp.to/unix/nonblock.html

  • ext/socket/lib/socket.rb (read_nonblock, write_nonblock): Linux-specific wrapper without side effects [ruby-core:80780] [Feature #13362]
  • test/socket/test_basicsocket.rb (test_read_write_nonblock): new test

Revision 58400
Added by normal about 2 years ago

socket: avoid fcntl for read/write_nonblock on Linux

On platforms where MSG_DONTWAIT works reliably on all sockets
(so far, I know of Linux), we can avoid fcntl syscalls and
implement IO#write_nonblock and IO#read_nonblock in terms of the
socket-specific send and recv family of syscalls.

This avoids side effects on the socket, and also encourages
generic code to be written in cases where IO wrappers like
OpenSSL::SSL::SSLSocket are used.

Perhaps in the future, side-effect-free non-blocking I/O can
be standard on all files and OSes: https://cr.yp.to/unix/nonblock.html

  • ext/socket/lib/socket.rb (read_nonblock, write_nonblock): Linux-specific wrapper without side effects [ruby-core:80780] [Feature #13362]
  • test/socket/test_basicsocket.rb (test_read_write_nonblock): new test

Revision 58400
Added by normal about 2 years ago

socket: avoid fcntl for read/write_nonblock on Linux

On platforms where MSG_DONTWAIT works reliably on all sockets
(so far, I know of Linux), we can avoid fcntl syscalls and
implement IO#write_nonblock and IO#read_nonblock in terms of the
socket-specific send and recv family of syscalls.

This avoids side effects on the socket, and also encourages
generic code to be written in cases where IO wrappers like
OpenSSL::SSL::SSLSocket are used.

Perhaps in the future, side-effect-free non-blocking I/O can
be standard on all files and OSes: https://cr.yp.to/unix/nonblock.html

  • ext/socket/lib/socket.rb (read_nonblock, write_nonblock): Linux-specific wrapper without side effects [ruby-core:80780] [Feature #13362]
  • test/socket/test_basicsocket.rb (test_read_write_nonblock): new test

Revision ba5eb645
Added by normal over 1 year ago

socket: fix BasicSocket#*_nonblock buffering bugs from r58400

IO#read_nonblock and IO#write_nonblock take into account
buffered data, so the Linux-only BasicSocket#read_nonblock
and BasicSocket#write_nonblock methods must, too.

This bug was only introduced in r58400
("socket: avoid fcntl for read/write_nonblock on Linux")
and does not affect any stable release.

  • ext/socket/basicsocket.c (rsock_init_basicsocket):
  • ext/socket/init.c (rsock_s_recvfrom_nonblock):
  • ext/socket/init.c (rsock_init_socket_init):
  • ext/socket/lib/socket.rb (def read_nonblock):
  • ext/socket/lib/socket.rb (def write_nonblock):
  • ext/socket/rubysocket.h (static inline void rsock_maybe_wait_fd):
  • test/socket/test_basicsocket.rb (def test_read_write_nonblock): [Feature #13362]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60496 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 60496
Added by normalperson (Eric Wong) over 1 year ago

socket: fix BasicSocket#*_nonblock buffering bugs from r58400

IO#read_nonblock and IO#write_nonblock take into account
buffered data, so the Linux-only BasicSocket#read_nonblock
and BasicSocket#write_nonblock methods must, too.

This bug was only introduced in r58400
("socket: avoid fcntl for read/write_nonblock on Linux")
and does not affect any stable release.

  • ext/socket/basicsocket.c (rsock_init_basicsocket):
  • ext/socket/init.c (rsock_s_recvfrom_nonblock):
  • ext/socket/init.c (rsock_init_socket_init):
  • ext/socket/lib/socket.rb (def read_nonblock):
  • ext/socket/lib/socket.rb (def write_nonblock):
  • ext/socket/rubysocket.h (static inline void rsock_maybe_wait_fd):
  • test/socket/test_basicsocket.rb (def test_read_write_nonblock): [Feature #13362]

Revision 60496
Added by normal over 1 year ago

socket: fix BasicSocket#*_nonblock buffering bugs from r58400

IO#read_nonblock and IO#write_nonblock take into account
buffered data, so the Linux-only BasicSocket#read_nonblock
and BasicSocket#write_nonblock methods must, too.

This bug was only introduced in r58400
("socket: avoid fcntl for read/write_nonblock on Linux")
and does not affect any stable release.

  • ext/socket/basicsocket.c (rsock_init_basicsocket):
  • ext/socket/init.c (rsock_s_recvfrom_nonblock):
  • ext/socket/init.c (rsock_init_socket_init):
  • ext/socket/lib/socket.rb (def read_nonblock):
  • ext/socket/lib/socket.rb (def write_nonblock):
  • ext/socket/rubysocket.h (static inline void rsock_maybe_wait_fd):
  • test/socket/test_basicsocket.rb (def test_read_write_nonblock): [Feature #13362]

Revision 60496
Added by normal over 1 year ago

socket: fix BasicSocket#*_nonblock buffering bugs from r58400

IO#read_nonblock and IO#write_nonblock take into account
buffered data, so the Linux-only BasicSocket#read_nonblock
and BasicSocket#write_nonblock methods must, too.

This bug was only introduced in r58400
("socket: avoid fcntl for read/write_nonblock on Linux")
and does not affect any stable release.

  • ext/socket/basicsocket.c (rsock_init_basicsocket):
  • ext/socket/init.c (rsock_s_recvfrom_nonblock):
  • ext/socket/init.c (rsock_init_socket_init):
  • ext/socket/lib/socket.rb (def read_nonblock):
  • ext/socket/lib/socket.rb (def write_nonblock):
  • ext/socket/rubysocket.h (static inline void rsock_maybe_wait_fd):
  • test/socket/test_basicsocket.rb (def test_read_write_nonblock): [Feature #13362]

History

Updated by normalperson (Eric Wong) about 2 years ago

normalperson@yhbt.net wrote:

Feature #13362: [PATCH] socket: avoid fcntl for read/write_nonblock on Linux
https://bugs.ruby-lang.org/issues/13362

Any comment?

Also, this patch avoids the race condition where another thread
or process can clear the nonblocking flag via fcntl immediately
after {read,write}_nonblock sets it and causes the
{read,write}_nonblock caller to get stuck.

Thanks.

Updated by akr (Akira Tanaka) about 2 years ago

  • Status changed from Open to Feedback

I think it's possible on such platforms.

If some non-Ruby application depend on nonblocking flag set by Ruby,
such application will be affected, though.
It is better style that such application set nonblocking flag explicitly.

Updated by normalperson (Eric Wong) about 2 years ago

akr@fsij.org wrote:

Issue #13362 has been updated by akr (Akira Tanaka).

Status changed from Open to Feedback

I think it's possible on such platforms.

If some non-Ruby application depend on nonblocking flag set by Ruby,
such application will be affected, though.

Yes, there may be some code which depends on side-effects.
However, I think it is a minor concern and anything which
inherits sockets ought to know to set flags correctly.

Normal Ruby code does not have this problem, since blocking
methods know to call rb_io_wait_*able on EAGAIN/EWOULDBLOCK.

It is better style that such application set nonblocking flag explicitly.

Right.

Should I commit?

Updated by akr (Akira Tanaka) about 2 years ago

I think we can try it to see the incompatibility is really minor or not.
So, it should be described in NEWS.

#5

Updated by Anonymous about 2 years ago

  • Status changed from Feedback to Closed

Applied in changeset trunk|r58400.


socket: avoid fcntl for read/write_nonblock on Linux

On platforms where MSG_DONTWAIT works reliably on all sockets
(so far, I know of Linux), we can avoid fcntl syscalls and
implement IO#write_nonblock and IO#read_nonblock in terms of the
socket-specific send and recv family of syscalls.

This avoids side effects on the socket, and also encourages
generic code to be written in cases where IO wrappers like
OpenSSL::SSL::SSLSocket are used.

Perhaps in the future, side-effect-free non-blocking I/O can
be standard on all files and OSes: https://cr.yp.to/unix/nonblock.html

  • ext/socket/lib/socket.rb (read_nonblock, write_nonblock): Linux-specific wrapper without side effects [ruby-core:80780] [Feature #13362]
  • test/socket/test_basicsocket.rb (test_read_write_nonblock): new test

Updated by normalperson (Eric Wong) about 2 years ago

akr@fsij.org wrote:

I think we can try it to see the incompatibility is really minor or not.
So, it should be described in NEWS.

OK, r58400.

I think Ruby 1.8 => 1.9 introduced similar minor incompatibility
for all pipe and sockets, too, since 1.8 always used
non-blocking I/O to implement blocking IO with green threads.

Also available in: Atom PDF