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; diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb index 8b4dc1ed98..1ca05ae362 100644 --- a/test/ruby/test_io.rb +++ b/test/ruby/test_io.rb @@ -3876,8 +3876,10 @@ __END__ end def test_open_fifo_does_not_block_other_threads - mkcdtmpdir { + mkcdtmpdir do File.mkfifo("fifo") + rescue NotImplementedError + else assert_separately([], <<-'EOS') t1 = Thread.new { open("fifo", "r") {|r| @@ -3892,8 +3894,32 @@ __END__ t1_value, _ = assert_join_threads([t1, t2]) assert_equal("foo", t1_value) EOS - } - end if /mswin|mingw|bccwin|cygwin/ !~ RUBY_PLATFORM + end + end + + def test_open_fifo_restart_at_signal_intterupt + mkcdtmpdir do + File.mkfifo("fifo") + rescue NotImplementedError + else + wait = EnvUtil.apply_timeout_scale(0.1) + data = "writing to fifo" + + # Do not use assert_separately, because reading from stdin + # prevents to reproduce [Bug #20708] + assert_in_out_err(["-e", "#{<<~"begin;"}\n#{<<~'end;'}"], [], [data]) + wait, data = #{wait}, #{data.dump} + ; + begin; + trap(:USR1) {} + Thread.new do + sleep wait; Process.kill(:USR1, $$) + sleep wait; File.write("fifo", data) + end + puts File.read("fifo") + end; + end + end if Signal.list[:USR1] # Pointless on platforms without signal def test_open_flag make_tempfile do |t|