Issue #17664 has been updated by ioquatix (Samuel Williams).
> I could probably use the 'events' form of IO#wait however.
Yes, you should do that. `IO.select` for a single file descriptor is hard to implement efficiently into the event loop.
----------------------------------------
Bug #17664: Behavior of sockets changed in Ruby 3.0 to non-blocking
https://bugs.ruby-lang.org/issues/17664#change-101669
* 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/78f188524f551c97b1a7a44ae1351…. 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/d3c9cf3ddc1f41438… is to make sure `O_NONBLOCK` is not set before attempting I/O operations on any fd.
--
https://bugs.ruby-lang.org/
Issue #19418 has been reported by wilhelmsen (Hallgeir Wilhelmsen).
----------------------------------------
Bug #19418: Checking if a date in an open date range times out when the range starts after the test date
https://bugs.ruby-lang.org/issues/19418
* Author: wilhelmsen (Hallgeir Wilhelmsen)
* Status: Open
* Priority: Normal
* ruby -v: 3.1.3
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
`
require 'date'
((Date.today + 1)..).include?(Date.today)
`
is expected to return `false`. It never return a value, as like it is in a never ending loop.
`((Date.today)..).include?(Date.today)`
however, returns `true` right away.
`(2..).include?(1)`
also returns false, as expected.
I.e. this seems to be a date issue and not a range issue, and it seem to happen when the start date comes after the date to check for.
--
https://bugs.ruby-lang.org/
Issue #19404 has been reported by alanwu (Alan Wu).
----------------------------------------
Bug #19404: Backport request for 3b83b265f11965582d4b9b439eff8a501792ab68
https://bugs.ruby-lang.org/issues/19404
* Author: alanwu (Alan Wu)
* Status: Closed
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: REQUIRED
----------------------------------------
It would be nice to have this in a release to make it
easier for people to send good crash diagnostics.
```
commit 3b83b265f11965582d4b9b439eff8a501792ab68
YJIT: Crash with rb_bug() when panicking
Helps with getting good bug reports in the wild. Intended to be
backported to the 3.2.x series.
yjit/bindgen/src/main.rs | 3 +++
yjit/src/cruby_bindings.inc.rs | 1 +
yjit/src/yjit.rs | 29 +++++++++++++++++++++++++++--
```
--
https://bugs.ruby-lang.org/
Issue #19385 has been reported by jwcooper (Justin Cooper).
----------------------------------------
Bug #19385: YJIT panicked while holding VM lock acquired at ./yjit/src/core.rs:1693. Aborting.
https://bugs.ruby-lang.org/issues/19385
* Author: jwcooper (Justin Cooper)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.2.0 (2022-12-25 revision a528908271) +YJIT [aarch64-linux]
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
Attached is a rust backtrace of an application crashing with a panic with yjit enabled.
This is only happening on our sidekiq processes on one of our applications in production. I'm uncertain where in our code it's crashing so far, as it's only crashing once every 20 minutes across 8 sidekiq processes running ~300 jobs/second. Our other applications running with 3.2.0 +yjit are running great on puma and sidekiq.
It may be related to, but I'm uncertain:
https://bugs.ruby-lang.org/issues/19299
---Files--------------------------------
backtrace.txt (8.71 KB)
--
https://bugs.ruby-lang.org/
Issue #19144 has been updated by kjtsanaktsidis (KJ Tsanaktsidis).
Thank you for having a look at this!
> Ruby has several methods to invoke getaddrinfo() and connect() internally, such as TCPSocket.new.
> How about we specify AI_ADDRCONFIG for getaddrinfo invocations in such methods?
I'm OK with doing just this, and not changing direct calls to `Addrinfo.getaddrinfo`. You're right, it's going to solve 99% of the problems and avoids any potential compatibility issue
> I don't understand why AI_V4MAPPED is useful.
I did a bit more research into this. Actually what I said in the original issue about NAT64 is wrong, v4 mapped v6 addresses have nothing to do with NAT64.
What this flag does _actually_ is:
* When making a call to getaddrinfo with both AF_INET6 and AI_V4MAPPED,
* If there is no AAAA record for a name,
* And there is an A record for a name,
* Return an "IPv4-mapped IPv6 address", which is an IPv6 address prefixed with `::FFFF` and then the four bytes of the IPv4 address at the end e.g. `::FFFF:1.2.3.4`
The point of the IPv4-mapped IPv6 address actually has nothing to do with NAT64. Rather, when calling `connect(2)` on such an IPv6 address, _if_ the host actually does have an IPv4 address as well, it will make the connection with the IPv4 stack. The purpose of this, it seems, is to allow applications to be written to only handle IPv6, and they'll transparently get IPv4 support for free.
I don't think Ruby actually needs this flag - it defaults to making the request with `AF_UNSPEC` and can handle getting either IPv4 or IPv6 addresses out of `getaddrinfo` correctly. In fact, the only way for any of the socket connect methods to pass a specific address family in here is `UDPSocket.new(Socket::AF_INET6).connect('hostname', port_number)`. If this actually made an IPv4 connection because getaddrinfo returned an IPv4-mapped IPv6 address, I think that would be very confusing.
So, I think you're right - we should not set `AI_V4MAPPED` by default.
> Also, some systems, such as NetBSD, seems doesn't have AI_V4MAPPED.
I would add feature checks for these flags in socket's `extconf.rb` i think.
----------------------------
Thanks again for your feedback. I'll try and send a PR later this week which defaults `AI_ADDRCONFIG` to on when `getaddrinfo` is called from inside the socket connection methods (but NOT when called explicitly with `Socket.getaddrinfo` et al).
----------------------------------------
Bug #19144: Ruby should set AI_V4MAPPED | AI_ADDRCONFIG getaddrinfo flags by default
https://bugs.ruby-lang.org/issues/19144#change-101648
* Author: kjtsanaktsidis (KJ Tsanaktsidis)
* Status: Feedback
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
Currently, DNS lookups made with `getaddrinfo` from Ruby (i.e. not from the `Resolv` module) cause both A and AAAA DNS requests to be made, even on systems that don’t actually have an IPv6 address that could possibly make the AAAA response useful. I wouldn’t _really_ care about this, normally, but glibc has a bug (https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/1961697) which can cause a 5-second delay in DNS lookups when both A and AAAA records are queried in parallel. This bug is fixed in glibc upstream but still present in some LTS linux distros (Ubuntu 18.04 and 20.04 at least), so I think it’s worthwhile to try and work around it in circumstances where the AAAA request is pointless anyway.
The dual A/AAAA lookup happens because whenever Ruby calls getaddrinfo to perform DNS lookups, it always sets `hints`, and sets `hints->ai_flags` to zero by default unless flags are specified by the caller (e.g. `AI_PASSIVE` is set when binding a TCP server socket in `TCPServer.new`).
This matches the default value of `ai_flags` specified by POSIX, which is zero. However, glibc behaves differently. When glibc’s `getaddrinfo` function is called with `NULL` for the `hints` parameter, it defaults the `ai_flags` value to `(AI_V4MAPPED | AI_ADDRCONFIG)`. The manpage (from the Linux man-pages project - https://man7.org/linux/man-pages/man3/getaddrinfo.3.html) claims “this is an improvement on the standard” (although I couldn’t find this mentioned in the glibc manual itself).
Of course, we’re not _actually_ ever calling `getaddrinfo` with NULL `hints`; so, we never actually use these flags on glibc systems (unless they’re explicitly specified by the caller).
My proposal is that we should change Ruby to set these two flags by default, when they’re available, in the following circumstances:
* In all calls made internally to `rsock_getaddrinfo` as a result of socket functions like `TCPSocket.new`, `UDPSocket.new`, etc.
* EXCEPT when `AI_PASSIVE` is also set (i.e. when we’re trying to get an address to bind for listener socket - see below)
* In calls made to `rsock_getaddrinfo` as a direct result of calling `Addrinfo.getaddrinfo` from Ruby with nil flags
* EXCEPT calls to `Addrinfo.getaddrinfo` where explicit flags are provided
Both of these seem like something you would almost always want to be doing in any outgoing connection scenario:
* `AI_V4MAPPED` ensures that, if AF_INET6 is explicitly specified as the desired protocol, and there is no AAAA record in DNS, that any A record that _is_ present gets converted to an IPv4-mapped IPv6 address so it can be used e.g. with NAT64.
* `AI_ADDRCONFIG` ensures that, if a machine has no IPv6 address, it doesn’t bother making an AAAA lookup that will return IPv6 addresses that can’t actually be used for anything (and vice versa for IPv4).
The reason why we wouldn’t want to set `AI_ADDRCONFIG` in circumstances where Ruby currently sets `AI_PASSIVE` is that loopback addresses are not considered in deciding if a system has an IPv4/IPv6 address. Conceivably, you might want to bind to a `::1` loopback address, and allow other processes on the same machine to connect to that.
Does changing this default sound reasonable? If so I can prepare a patch. Another option I considered is doing this _only_ when Ruby is built against glibc (so that other system behaviour is most closely matched).
--
https://bugs.ruby-lang.org/
Issue #15778 has been updated by Eregon (Benoit Daloze).
st0012 (Stan Lo) wrote in #note-19:
> my understanding is that such feature requires Ruby to keep all the frames on the stack in an accessible format, which will limit the optimisation YJIT could do.
I don't think so since `rb_debug_inspector_open()` already exposes that, having it as a Ruby method doesn't really change much from an optimization POV AFAIK.
But yes, it's very expensive to get the bindings of all frames, especially with a deep stack e.g. in Rails apps (e.g., it causes deoptimization of the stack frames).
A thought: maybe the new `Thread.each_caller_location` could have a `debug: true`/`binding: true` keyword argument.
That would make it possible to only get the binding for the first N frames, which is much faster than for all frames.
And it would also encourage to not hold onto such bindings for long (which would otherwise be a sort of leak), good.
----------------------------------------
Feature #15778: Expose an API to pry-open the stack frames in Ruby
https://bugs.ruby-lang.org/issues/15778#change-101646
* Author: gsamokovarov (Genadi Samokovarov)
* Status: Open
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
Hello,
I'm the maintainer of the web-console (https://github.com/rails/web-console/) gem, where one of our features is to jump between the frames in which an error occurred. To accomplish this, I currently use the Debug Inspector CRuby API. I think we should expose this functionality in Rubyland, so tools like web-console don't need to resort to C code for this. This also makes it quite harder for me to support different implementations like JRuby or TruffleRuby as everyone is having a different way to create Ruby Binding objects that represent the frames.
Here the API ideas:
Add `Thread::Backtrace::Location#binding` method that can create a binding for a specific caller of the current frame. We can reuse the existing `Kernel.caller_locations` method to generate the array of `Thread::Backtrace::Location` objects. We can optionally have the `Kernel.caller_locations(debug: true)` argument if we cannot generate the bindings lazily on the VM that can instruct the VM to do the slower operation.
- `Thread::Backtrace::Location#binding` returns `Binding|nil`. Nil result may mean that the current location is a C frame or a JITted/optimized frame and we cannot debug it.
We can also expose the DebugInspector API directly, as done in the https://github.com/banister/debug_inspector gem, but for tools like web-console, we'd need to map the bindings with the backtrace, as we cannot generate Bindings for every frame (C frames) and this needs to be done in application code, so I think the `Thread::Backtrace::Location#binding` is the better API for Ruby-land.
Such API can help us eventually write most of our debuggers in Ruby as right now we don't have a way to do Post-Mortem debugging without native code or even start our debuggers without monkey-patching `Binding`.
I have presented this idea in a RubyKaigi's 2019 talk called "Writing Debuggers in Plain Ruby", you can check-out the slides for more context: http://kaigi-debuggers-in-ruby.herokuapp.com.
--
https://bugs.ruby-lang.org/
Issue #19413 has been reported by luke-gru (Luke Gruber).
----------------------------------------
Bug #19413: Can't move object when 2 ivars refer to same object
https://bugs.ruby-lang.org/issues/19413
* Author: luke-gru (Luke Gruber)
* Status: Open
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
```ruby
class A
def initialize
@a = Object.new
@b = @a
end
end
r = Ractor.new do |err|
obj = receive
p obj
end
r.send(A.new, move: true) # Allocator undefined for Ractor::MovedObject
r.take
```
To fix it we could have a hash of old to new objects during traversal/replacement and use the same new object over again if necessary.
--
https://bugs.ruby-lang.org/
Issue #19144 has been updated by akr (Akira Tanaka).
Status changed from Open to Feedback
I feel AI_ADDRCONFIG is good if the result addresses are used immediately for making a connection.
But getaddrinfo can be used just for getting DNS information.
AI_ADDRCONFIG is not suitable for this situation.
I don't understand why AI_V4MAPPED is useful.
Also, some systems, such as NetBSD, seems doesn't have AI_V4MAPPED.
https://man.netbsd.org/NetBSD-9.3/getaddrinfo.3
Using AI_V4MAPPED introduces incompatibility.
Ruby has several methods to invoke getaddrinfo() and connect() internally, such as TCPSocket.new.
How about we specify AI_ADDRCONFIG for getaddrinfo invocations in such methods?
This avoids the problem (useless AAAA query) and
doesn't affect applications that invoke of getaddrinfo (possibly it may have a problem with AI_ADDRCONFIG).
----------------------------------------
Bug #19144: Ruby should set AI_V4MAPPED | AI_ADDRCONFIG getaddrinfo flags by default
https://bugs.ruby-lang.org/issues/19144#change-101644
* Author: kjtsanaktsidis (KJ Tsanaktsidis)
* Status: Feedback
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
Currently, DNS lookups made with `getaddrinfo` from Ruby (i.e. not from the `Resolv` module) cause both A and AAAA DNS requests to be made, even on systems that don’t actually have an IPv6 address that could possibly make the AAAA response useful. I wouldn’t _really_ care about this, normally, but glibc has a bug (https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/1961697) which can cause a 5-second delay in DNS lookups when both A and AAAA records are queried in parallel. This bug is fixed in glibc upstream but still present in some LTS linux distros (Ubuntu 18.04 and 20.04 at least), so I think it’s worthwhile to try and work around it in circumstances where the AAAA request is pointless anyway.
The dual A/AAAA lookup happens because whenever Ruby calls getaddrinfo to perform DNS lookups, it always sets `hints`, and sets `hints->ai_flags` to zero by default unless flags are specified by the caller (e.g. `AI_PASSIVE` is set when binding a TCP server socket in `TCPServer.new`).
This matches the default value of `ai_flags` specified by POSIX, which is zero. However, glibc behaves differently. When glibc’s `getaddrinfo` function is called with `NULL` for the `hints` parameter, it defaults the `ai_flags` value to `(AI_V4MAPPED | AI_ADDRCONFIG)`. The manpage (from the Linux man-pages project - https://man7.org/linux/man-pages/man3/getaddrinfo.3.html) claims “this is an improvement on the standard” (although I couldn’t find this mentioned in the glibc manual itself).
Of course, we’re not _actually_ ever calling `getaddrinfo` with NULL `hints`; so, we never actually use these flags on glibc systems (unless they’re explicitly specified by the caller).
My proposal is that we should change Ruby to set these two flags by default, when they’re available, in the following circumstances:
* In all calls made internally to `rsock_getaddrinfo` as a result of socket functions like `TCPSocket.new`, `UDPSocket.new`, etc.
* EXCEPT when `AI_PASSIVE` is also set (i.e. when we’re trying to get an address to bind for listener socket - see below)
* In calls made to `rsock_getaddrinfo` as a direct result of calling `Addrinfo.getaddrinfo` from Ruby with nil flags
* EXCEPT calls to `Addrinfo.getaddrinfo` where explicit flags are provided
Both of these seem like something you would almost always want to be doing in any outgoing connection scenario:
* `AI_V4MAPPED` ensures that, if AF_INET6 is explicitly specified as the desired protocol, and there is no AAAA record in DNS, that any A record that _is_ present gets converted to an IPv4-mapped IPv6 address so it can be used e.g. with NAT64.
* `AI_ADDRCONFIG` ensures that, if a machine has no IPv6 address, it doesn’t bother making an AAAA lookup that will return IPv6 addresses that can’t actually be used for anything (and vice versa for IPv4).
The reason why we wouldn’t want to set `AI_ADDRCONFIG` in circumstances where Ruby currently sets `AI_PASSIVE` is that loopback addresses are not considered in deciding if a system has an IPv4/IPv6 address. Conceivably, you might want to bind to a `::1` loopback address, and allow other processes on the same machine to connect to that.
Does changing this default sound reasonable? If so I can prepare a patch. Another option I considered is doing this _only_ when Ruby is built against glibc (so that other system behaviour is most closely matched).
--
https://bugs.ruby-lang.org/
Issue #14083 has been updated by alanwu (Alan Wu).
Status changed from Open to Rejected
This is working as intended. Scoping rules for refinements is similar
to the scoping rules for constant resolution. The scope only
changes when one uses the `class`/`module` keyword. In the posted
example the two `using` calls act on the same scope; the refinement
scope does not end when the block scope ends.
See also: https://bugs.ruby-lang.org/issues/11779#note-31
----------------------------------------
Bug #14083: Refinement in block calling incorrect method
https://bugs.ruby-lang.org/issues/14083#change-101640
* Author: bjfish (Brandon Fish)
* Status: Rejected
* Priority: Normal
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN
----------------------------------------
Tested on ruby versions 2.3.4 and 2.4.1
When a refinement is used inside a block, the scope of the refinement is not ending when the block has ended. The following example illustrates the issue:
Example:
~~~ ruby
class Example
def test
puts "Example#test"
end
end
module M1
refine Example do
def test
puts "Example#test in M1"
end
end
end
module M2
refine Example do
def test
puts "Example#test in M2"
end
end
end
e = Example.new
[M1, M2].each { |r|
e.test
using r
e.test
}
~~~
Actual Output
~~~ text
Example#test
Example#test in M1
Example#test in M1
Example#test in M2
~~~
Expected output
~~~ text
Example#test
Example#test in M1
Example#test
Example#test in M2
~~~
--
https://bugs.ruby-lang.org/