Bug #20708
openEINTR while opening fifo isn't retried
Description
I don't think this should fail:
martind@stormy:~/download/ruby$ rm -f /tmp/badger && mkfifo /tmp/badger && timeout 2 ./ruby --disable-gems -we 'fork() {}; IO.read("/tmp/badger")'
-e:1:in 'IO.read': Interrupted system call @ rb_sysopen - /tmp/badger (Errno::EINTR)
from -e:1:in '<main>'
martind@stormy:~/download/ruby$
The behavior changed with 2.6.0-preview3 compared to 2.6.0-preview2:
martind@stormy:~/download/ruby-2.6.0-preview2$ rm -f /tmp/badger && mkfifo /tmp/badger && timeout 2 ./ruby --disable-gems -we 'fork() {}; IO.read("/tmp/badger")'
martind@stormy:~/download/ruby-2.6.0-preview3$ rm -f /tmp/badger && mkfifo /tmp/badger && timeout 2 ./ruby --disable-gems -we 'fork() {}; IO.read("/tmp/badger")'
Traceback (most recent call last):
1: from -e:1:in `<main>'
-e:1:in `read': Interrupted system call @ rb_sysopen - /tmp/badger (Errno::EINTR)
martind@stormy:~/download/ruby-2.6.0-preview3$
I don't know what the consequences would be, so I don't mean this as a serious suggestion:
martind@stormy:~/download/ruby$ git diff
diff --git a/io.c b/io.c
index 54b60b7357..590e8d11d7 100644
--- a/io.c
+++ b/io.c
@@ -6956,7 +6956,10 @@ sysopen_func(void *ptr)
static inline int
rb_sysopen_internal(struct sysopen_struct *data)
{
- int fd = IO_WITHOUT_GVL_INT(sysopen_func, data);
+ int fd;
+ do {
+ fd = IO_WITHOUT_GVL_INT(sysopen_func, data);
+ } while (fd < 0 && errno == EINTR);
if (0 <= fd)
rb_update_max_fd(fd);
return fd;
martind@stormy:~/download/ruby$
... but it fixes this particular test case, for me, with today's Ruby from github.
There were negligible differences between 2.6.0-preview{2,3} in io.c but the SIGCHLD handling was changed.
The test case is reliable for me on at least:
Linux stormy 4.19.0-26-amd64 #1 SMP Debian 4.19.304-1 (2024-01-09) x86_64 GNU/Linux
Linux moritz 5.10.0-14-amd64 #1 SMP Debian 5.10.113-1 (2022-04-29) x86_64 GNU/Linux
I hope it's independent of the kernel, as:
https://man7.org/linux/man-pages/man7/signal.7.html
... teaches:
otherwise the call fails with the error EINTR:
...
• open(2), if it can block (e.g., when opening a FIFO; see
fifo(7)).
No data to display