ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:96642] [Ruby master Bug#16476] Socket.getaddrinfo cannot be interrupted by Timeout.timeout
       [not found] <redmine.issue-16476.20200103134928@ruby-lang.org>
@ 2020-01-03 13:49 ` shatrov
  2020-01-07 15:37 ` [ruby-core:96704] " daniel
  2020-01-10  2:47 ` [ruby-core:96751] " shatrov
  2 siblings, 0 replies; 3+ messages in thread
From: shatrov @ 2020-01-03 13:49 UTC (permalink / raw)
  To: ruby-core

Issue #16476 has been reported by kirs (Kir Shatrov).

----------------------------------------
Bug #16476: Socket.getaddrinfo cannot be interrupted by Timeout.timeout
https://bugs.ruby-lang.org/issues/16476

* Author: kirs (Kir Shatrov)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
It seems like the blocking syscall done by `Socket.getaddrinfo` blocks Ruby VM in a way that Timeout.timeout has no effect.
See reproduction steps in getaddrinfo_interrupt.rb attached. This affects all modern Ruby versions, including the latest 2.7.0.

Combined with default 10s resolv timeout on many Linux systems, this can have a very noticeable effect on production Ruby apps being not resilient to slow DNS resolutions, and being unable to fail fast even with `Timeout.timeout`.

While https://bugs.ruby-lang.org/issues/15553 improves the situation, `Socket.getaddrinfo` is still blocking the VM and Timeout has no effect.

I'd like to discuss what could be done to make that call non-blocking for threads in Ruby VM.

---Files--------------------------------
getaddrinfo_interrupt.rb (881 Bytes)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [ruby-core:96704] [Ruby master Bug#16476] Socket.getaddrinfo cannot be interrupted by Timeout.timeout
       [not found] <redmine.issue-16476.20200103134928@ruby-lang.org>
  2020-01-03 13:49 ` [ruby-core:96642] [Ruby master Bug#16476] Socket.getaddrinfo cannot be interrupted by Timeout.timeout shatrov
@ 2020-01-07 15:37 ` daniel
  2020-01-10  2:47 ` [ruby-core:96751] " shatrov
  2 siblings, 0 replies; 3+ messages in thread
From: daniel @ 2020-01-07 15:37 UTC (permalink / raw)
  To: ruby-core

Issue #16476 has been updated by Dan0042 (Daniel DeLorme).


+1

This has been an issue for a very long time, and it's often been handled by installing an asynchronous DNS resolver gem, but it would be nice if it "just worked". If it's really as simple as using `getaddrinfo_a`, that sounds great.

----------------------------------------
Bug #16476: Socket.getaddrinfo cannot be interrupted by Timeout.timeout
https://bugs.ruby-lang.org/issues/16476#change-83690

* Author: kirs (Kir Shatrov)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
It seems like the blocking syscall done by `Socket.getaddrinfo` blocks Ruby VM in a way that Timeout.timeout has no effect.
See reproduction steps in getaddrinfo_interrupt.rb attached. This affects all modern Ruby versions, including the latest 2.7.0.

Combined with default 10s resolv timeout on many Linux systems, this can have a very noticeable effect on production Ruby apps being not resilient to slow DNS resolutions, and being unable to fail fast even with `Timeout.timeout`.

While https://bugs.ruby-lang.org/issues/15553 improves the situation for `Addrinfo.getaddrinfo`, `Socket.getaddrinfo` is still blocking the VM and Timeout has no effect.

I'd like to discuss what could be done to make that call non-blocking for threads in Ruby VM.

**UPD:** looking closer, I can see that `Socket.getaddrinfo("www.ruby-lang.org", "http")` and `Addrinfo.getaddrinfo("www.ruby-lang.org", "http")` call non-interruptible `getaddrinfo`, while `Addrinfo.getaddrinfo("www.ruby-lang.org", "http", timeout: 10)` calls `getaddrinfo_a`, which is interruptible:

``` ruby
# interrupts as expected
Timeout.timeout(1) do
  Addrinfo.getaddrinfo("www.ruby-lang.org", "http", timeout: 10)
end
```

I'd maybe suggest that we try to *always* use `getaddrinfo_a` when it's available, including in `Socket.getaddrinfo`. What downsides that would have?
I'd be happy to work on a patch.

---Files--------------------------------
getaddrinfo_interrupt.rb (881 Bytes)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [ruby-core:96751] [Ruby master Bug#16476] Socket.getaddrinfo cannot be interrupted by Timeout.timeout
       [not found] <redmine.issue-16476.20200103134928@ruby-lang.org>
  2020-01-03 13:49 ` [ruby-core:96642] [Ruby master Bug#16476] Socket.getaddrinfo cannot be interrupted by Timeout.timeout shatrov
  2020-01-07 15:37 ` [ruby-core:96704] " daniel
@ 2020-01-10  2:47 ` shatrov
  2 siblings, 0 replies; 3+ messages in thread
From: shatrov @ 2020-01-10  2:47 UTC (permalink / raw)
  To: ruby-core

Issue #16476 has been updated by kirs (Kir Shatrov).


Dan0042 (Daniel DeLorme) wrote:
> +1
> 
> This has been an issue for a very long time, and it's often been handled by installing an asynchronous DNS resolver gem, but it would be nice if it "just worked". If it's really as simple as using `getaddrinfo_a`, that sounds great.

Thanks for feedback Daniel!

I've put a PR with the suggested fix: https://github.com/ruby/ruby/pull/2827

----------------------------------------
Bug #16476: Socket.getaddrinfo cannot be interrupted by Timeout.timeout
https://bugs.ruby-lang.org/issues/16476#change-83741

* Author: kirs (Kir Shatrov)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
It seems like the blocking syscall done by `Socket.getaddrinfo` blocks Ruby VM in a way that Timeout.timeout has no effect.
See reproduction steps in getaddrinfo_interrupt.rb attached. This affects all modern Ruby versions, including the latest 2.7.0.

Combined with default 10s resolv timeout on many Linux systems, this can have a very noticeable effect on production Ruby apps being not resilient to slow DNS resolutions, and being unable to fail fast even with `Timeout.timeout`.

While https://bugs.ruby-lang.org/issues/15553 improves the situation for `Addrinfo.getaddrinfo`, `Socket.getaddrinfo` is still blocking the VM and Timeout has no effect.

I'd like to discuss what could be done to make that call non-blocking for threads in Ruby VM.

**UPD:** looking closer, I can see that `Socket.getaddrinfo("www.ruby-lang.org", "http")` and `Addrinfo.getaddrinfo("www.ruby-lang.org", "http")` call non-interruptible `getaddrinfo`, while `Addrinfo.getaddrinfo("www.ruby-lang.org", "http", timeout: 10)` calls `getaddrinfo_a`, which is interruptible:

``` ruby
# interrupts as expected
Timeout.timeout(1) do
  Addrinfo.getaddrinfo("www.ruby-lang.org", "http", timeout: 10)
end
```

I'd maybe suggest that we try to *always* use `getaddrinfo_a` when it's available, including in `Socket.getaddrinfo`. What downsides that would have?
I'd be happy to work on a patch.

---Files--------------------------------
getaddrinfo_interrupt.rb (881 Bytes)


-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-01-10  2:47 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <redmine.issue-16476.20200103134928@ruby-lang.org>
2020-01-03 13:49 ` [ruby-core:96642] [Ruby master Bug#16476] Socket.getaddrinfo cannot be interrupted by Timeout.timeout shatrov
2020-01-07 15:37 ` [ruby-core:96704] " daniel
2020-01-10  2:47 ` [ruby-core:96751] " shatrov

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).