From: samuel@... Date: 2021-07-11T10:05:10+00:00 Subject: [ruby-core:104578] [Ruby master Bug#17664] Behavior of sockets changed in Ruby 3.0 to non-blocking Issue #17664 has been updated by ioquatix (Samuel Williams). Here are some summaries from `strace -c`: Using non-blocking sockets: ``` % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ------------------ 28.10 0.621514 5 119770 close 25.50 0.564066 4 119530 write 18.39 0.406707 3 119532 2 accept4 14.50 0.320830 2 119844 1 read 13.39 0.296214 2 119922 9 newfstatat 0.04 0.000961 1 494 260 openat 0.02 0.000361 1 186 mmap 0.02 0.000333 0 551 551 readlink 0.01 0.000227 2 87 munmap 0.01 0.000138 2 54 brk 0.01 0.000116 4 26 getdents64 0.00 0.000097 1 80 fcntl 0.00 0.000062 6 9 1 io_uring_enter 0.00 0.000059 0 63 mprotect 0.00 0.000036 0 131 128 ioctl 0.00 0.000030 10 3 getsockname 0.00 0.000029 0 53 geteuid 0.00 0.000028 5 5 2 connect 0.00 0.000027 27 1 io_uring_setup 0.00 0.000026 0 53 getegid 0.00 0.000025 0 52 getuid 0.00 0.000025 0 52 getgid 0.00 0.000020 2 7 socket 0.00 0.000014 2 7 4 prctl 0.00 0.000008 1 5 futex 0.00 0.000007 1 7 rt_sigprocmask 0.00 0.000004 1 3 getpid 0.00 0.000004 2 2 bind 0.00 0.000003 1 2 sendto 0.00 0.000003 1 3 recvmsg 0.00 0.000003 3 1 listen 0.00 0.000002 0 73 lseek 0.00 0.000002 1 2 1 recvfrom 0.00 0.000002 2 1 setsockopt 0.00 0.000001 1 1 ppoll 0.00 0.000000 0 17 rt_sigaction 0.00 0.000000 0 6 pread64 0.00 0.000000 0 1 1 access 0.00 0.000000 0 1 execve 0.00 0.000000 0 1 getcwd 0.00 0.000000 0 1 sysinfo 0.00 0.000000 0 1 sigaltstack 0.00 0.000000 0 2 1 arch_prctl 0.00 0.000000 0 1 gettid 0.00 0.000000 0 1 sched_getaffinity 0.00 0.000000 0 1 set_tid_address 0.00 0.000000 0 1 timer_create 0.00 0.000000 0 1 clock_gettime 0.00 0.000000 0 1 set_robust_list 0.00 0.000000 0 2 eventfd2 0.00 0.000000 0 3 prlimit64 0.00 0.000000 0 1 getrandom ------ ----------- ----------- --------- --------- ------------------ 100.00 2.211984 3 600654 961 total ``` Using blocking sockets: ``` % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ------------------ 23.74 0.504460 5 92066 1 io_uring_enter 22.62 0.480659 5 92300 close 16.98 0.360809 1 184200 fcntl 14.83 0.315110 3 92062 2 accept4 11.16 0.237053 2 92373 read 10.55 0.224161 2 92452 9 newfstatat 0.03 0.000714 1 494 260 openat 0.02 0.000484 0 551 551 readlink 0.01 0.000274 4 62 brk 0.01 0.000262 3 87 munmap 0.01 0.000255 1 186 mmap 0.01 0.000210 1 130 127 ioctl 0.01 0.000123 1 63 mprotect 0.00 0.000082 1 73 lseek 0.00 0.000036 2 17 rt_sigaction 0.00 0.000030 0 53 geteuid 0.00 0.000027 0 52 getuid 0.00 0.000026 0 52 getgid 0.00 0.000026 0 53 getegid 0.00 0.000019 0 26 getdents64 0.00 0.000009 4 2 eventfd2 0.00 0.000005 0 7 rt_sigprocmask 0.00 0.000005 5 1 getrandom 0.00 0.000004 4 1 sysinfo 0.00 0.000004 4 1 timer_create 0.00 0.000003 1 3 getpid 0.00 0.000003 3 1 sigaltstack 0.00 0.000003 0 5 futex 0.00 0.000000 0 6 pread64 0.00 0.000000 0 1 1 access 0.00 0.000000 0 7 socket 0.00 0.000000 0 5 2 connect 0.00 0.000000 0 2 sendto 0.00 0.000000 0 2 1 recvfrom 0.00 0.000000 0 3 recvmsg 0.00 0.000000 0 2 bind 0.00 0.000000 0 1 listen 0.00 0.000000 0 3 getsockname 0.00 0.000000 0 1 setsockopt 0.00 0.000000 0 1 execve 0.00 0.000000 0 1 getcwd 0.00 0.000000 0 7 4 prctl 0.00 0.000000 0 2 1 arch_prctl 0.00 0.000000 0 1 gettid 0.00 0.000000 0 1 sched_getaffinity 0.00 0.000000 0 1 set_tid_address 0.00 0.000000 0 1 clock_gettime 0.00 0.000000 0 1 ppoll 0.00 0.000000 0 1 set_robust_list 0.00 0.000000 0 3 prlimit64 0.00 0.000000 0 1 io_uring_setup ------ ----------- ----------- --------- --------- ------------------ 100.00 2.124856 3 647427 959 total ``` Based on this, maybe my implementation of `read` is not working correctly. I'll have to check it, but generally, you can see the big difference. ---------------------------------------- Bug #17664: Behavior of sockets changed in Ruby 3.0 to non-blocking https://bugs.ruby-lang.org/issues/17664#change-92860 * Author: ciconia (Sharon Rosner) * Status: Assigned * Priority: Normal * Assignee: ioquatix (Samuel Williams) * ruby -v: 3.0.0 * Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN ---------------------------------------- I'm not sure this is a bug, but apparently a change was introduced in Ruby 3.0 that makes sockets non-blocking by default. This change was apparently introduced as part of the work on the [FiberScheduler interface](https://github.com/ruby/ruby/blame/78f188524f551c97b1a7a44ae13514729f1a21c7/ext/socket/init.c#L411-L434). This change of behaviour is not discussed in the Ruby 3.0.0 release notes. This change complicates the implementation of an io_uring-based fiber scheduler, since io_uring SQE's on fd's with `O_NONBLOCK` can return `EAGAIN` just like normal syscalls. Using io_uring with non-blocking fd's defeats the whole purpose of using io_uring in the first place. A workaround I have put in place in the Polyphony [io_uring backend](https://github.com/digital-fabric/polyphony/blob/d3c9cf3ddc1f414387948fa40e5f6a24f68bf045/ext/polyphony/backend_io_uring.c#L28-L47) is to make sure `O_NONBLOCK` is not set before attempting I/O operations on any fd. -- https://bugs.ruby-lang.org/ Unsubscribe: