Issue #19876 has been reported by kddnewton (Kevin Newton).
----------------------------------------
Bug #19876: Equality chaining
https://bugs.ruby-lang.org/issues/19876
* Author: kddnewton (Kevin Newton)
* Status: Open
* Priority: Normal
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
It appears that you cannot chain `==`, `!=`, `<=>`, `=~`, `!~`, `===`:
``` ruby
foo == bar == baz
```
but you can chain all of the other operators:
``` ruby
1 << 2 << 3
```
I'm not sure if I've missed some. I would just like to know if this is a bug. If it's not, then I need to know which operators cannot be chained. At the moment all of these can be chained in YARP, but if it's desired behavior that that is a syntax error, I need to explicitly disallow this.
--
https://bugs.ruby-lang.org/
Issue #19737 has been reported by unasuke (Yusuke Nakamura).
----------------------------------------
Feature #19737: Add `IO::Buffer#cat` for concat `IO::Buffer` instances
https://bugs.ruby-lang.org/issues/19737
* Author: unasuke (Yusuke Nakamura)
* Status: Open
* Priority: Normal
----------------------------------------
## motivation
In my use case, I want to concat two IO::Buffer instances. But current implementation doesn't have that way.
Then I created a patch. Opend here: TBD
## concern
I have two concerns about it.
### 1. Should we provide `IO::Buffer#+` as an alias?
In String instance, `"a" + "b"` returns `"ab",`. It feels intuitive.
So, should we provide the same way as `IO::Buffer.for("a") + IO::Buffer.for("b")`?
If `+` is provided, I naturally assume that `*` is also provided as an operator.
Should we also provide an `IO::Buffer#*` method for symmetry with the String class?
I thought the behavior of the "*" method is not obvious to me... (Is it right to just return joined buffers?)
### 2. Should it accept multiple IO::Buffer instances?
In the `cat` command, it accepts multiple inputs like this.
```
$ cat a.txt b.txt c.txt
a
b
c
```
Should `IO::Buffer#cat` accept multiple inputs too?
--
https://bugs.ruby-lang.org/
Issue #19790 has been reported by byroot (Jean Boussier).
----------------------------------------
Feature #19790: Optionally write Ruby crash reports into a file rather than STDERR
https://bugs.ruby-lang.org/issues/19790
* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
----------------------------------------
### Use case
On our servers we set [`/proc/sys/kernel/core_pattern`](https://man7.org/linux/man-pages/man5/core.5.html) to point to a small utility that report all the crashes happening in production with the associated core dump into BugSnag.
This allowed us to find and fix many Ruby and native extensions bugs in the last few years.
However, these are hard to triage, so we'd like to augment these crash reports with the output of `rb_vm_bugreport()`.
### Problem
`rb_vm_bugreport()` is hard coded to print to STDERR, this makes it hard to extract and parse the report in a production environment, as very often STDERR is shared with other processes, so the crash report is intertwined with logs from other processes.
### Feature Request
It would be very useful if Ruby could write the crash report to an arbitrary path rather than STDERR, akin to `kernel/core_pattern`.
Especially it would be useful if it supported interpolating the crashing process PID with `%p` like `kernel/core_pattern`, as it would make it easier to map that report with the core file.
This could be controller by an environment variable such as `RUBY_BUGREPORT_PATH`. e.g.
```
RUBY_BUGREPORT_PATH=/var/log/ruby/ruby-crash-pid-%p.log
```
### Optional Features
`kernel/core_pattern` supports other interpolations, however not all of them would make sense for Ruby to support.
%% A single % character.
%c Core file size soft resource limit of crashing process
(since Linux 2.6.24).
%d Dump mode—same as value returned by prctl(2)
PR_GET_DUMPABLE (since Linux 3.7).
%e The process or thread's comm value, which typically is
the same as the executable filename (without path prefix,
and truncated to a maximum of 15 characters), but may
have been modified to be something different; see the
discussion of /proc/pid/comm and /proc/pid/task/tid/comm
in proc(5).
%E Pathname of executable, with slashes ('/') replaced by
exclamation marks ('!') (since Linux 3.0).
%g Numeric real GID of dumped process.
%h Hostname (same as nodename returned by uname(2)).
%i TID of thread that triggered core dump, as seen in the
PID namespace in which the thread resides (since Linux
3.18).
%I TID of thread that triggered core dump, as seen in the
initial PID namespace (since Linux 3.18).
%p PID of dumped process, as seen in the PID namespace in
which the process resides.
%P PID of dumped process, as seen in the initial PID
namespace (since Linux 3.12).
%s Number of signal causing dump.
%t Time of dump, expressed as seconds since the Epoch,
1970-01-01 00:00:00 +0000 (UTC).
%u Numeric real UID of dumped process.
Additionally, if `kernel/core_pattern` starts with a pipe (`|`), then it allows to pipe the core dump to another program, this may also make sense as a feature.
### Prior Art
Aside from `kernel/core_pattern`, some other virtual machine have a similar feature, for instance the JVM has a configurable crash report:
```
-XX:ErrorFile=/var/log/java/hs_err_pid%p.log
```
--
https://bugs.ruby-lang.org/
Issue #19871 has been reported by konsolebox (K B).
----------------------------------------
Feature #19871: Add __owner__
https://bugs.ruby-lang.org/issues/19871
* Author: konsolebox (K B)
* Status: Open
* Priority: Normal
----------------------------------------
Which will give the owner of the currently executing method.
`method(__method__).owner` or `method(__callee__).owner` isn't enough since it may return a different owner if the method is overridden.
Relying on calling the name of its owner is also theoretically not reliable since the constant can be overshadowed and it makes code less portable when moving it from one namespace to another.
--
https://bugs.ruby-lang.org/
Issue #19844 has been reported by narine_moss(a)yahoo.com (Narine Mossikyan).
----------------------------------------
Bug #19844: Ruby 3.2 fails to build with openssl version 3
https://bugs.ruby-lang.org/issues/19844
* Author: narine_moss(a)yahoo.com (Narine Mossikyan)
* Status: Open
* Priority: Normal
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
Ruby version 3.2 code base: https://github.com/ruby/ruby/tree/1c7624469880bcb964be09a49e4907873f45b026
openssl v3 is installed under /usr/local_ssl_3.0.0.
./configure --with-openssl-dir=/usr/local_ssl_3.0.0
I get the following error when running make:
openssl_missing.c:24:13: error: dereferencing pointer to incomplete type ‘X509_CRL {aka const struct X509_crl_st}’
*psig = crl->signature;
^~
openssl_missing.c: In function ‘ossl_X509_REQ_get0_signature’:
openssl_missing.c:36:13: error: dereferencing pointer to incomplete type ‘X509_REQ {aka const struct X509_req_st}’
*psig = req->signature;
^~
I am trying to build ruby 3.2 with openssl version 3 to install it on ubuntu 22 that only has openssl v3. Can you advise me how to configure ruby to bypass this error?
--
https://bugs.ruby-lang.org/
Issue #19765 has been reported by Ethan (Ethan -).
----------------------------------------
Bug #19765: Ractor.make_shareable ignores self of a proc created from a Method
https://bugs.ruby-lang.org/issues/19765
* Author: Ethan (Ethan -)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.3.0dev (2023-07-12T00:26:03Z master dfe782be17) [x86_64-darwin21]
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
An unshareable receiver of a Proc or a Method will cause make_shareable to error, but this does not happen with a proc from Method#to_proc:
```ruby
str = ""
a = str.instance_exec { proc { to_s } }
Ractor.make_shareable a
# => <internal:ractor>:820:in `make_shareable': Proc's self is not shareable: #<Proc:0x00000001064b62c8 (irb):1> (Ractor::IsolationError)
b = str.instance_exec { method(:to_s) }
Ractor.make_shareable b
# => <internal:ractor>:820:in `make_shareable': can not make shareable object for #<Method: String#to_s()> (Ractor::Error)
c = str.instance_exec { method(:to_s).to_proc }
Ractor.make_shareable c
c.call
# => ""
str[0] = "!"
c.call
# => "!"
```
Related, maybe:
#19372
#19374
Tangential: why does Proc cause Ractor::IsolationError but Method causes Ractor::Error?
--
https://bugs.ruby-lang.org/
Issue #19075 has been updated by mame (Yusuke Endoh).
I think the workaround is good enough. Do you have a good use case to introduce this?
The proposed behavior is not something that can simply be called "last".
The traditional behavior requires a given block to return `false` for elements in the first half and `true` for elements in the second half. On the other hand, this proposal requires it to return `true` for the first half and `false` for the second half.
The name `bsearch_last` is never clear enough to me for this behavior. `bsearch_rindex` and `rbsearch` are not good either.
`bsearch` is confusing, and this proposed mode is even more confusing. I don't think it is a good idea to make this mode selectable by a keyword argument.
----------------------------------------
Feature #19075: Binary searching for the last element
https://bugs.ruby-lang.org/issues/19075#change-104510
* Author: kyanagi (Kouhei Yanagita)
* Status: Open
* Priority: Normal
----------------------------------------
My latest proposal is https://bugs.ruby-lang.org/issues/19075#note-6.
I will leave the initial proposal below.
---
PR: https://github.com/ruby/ruby/pull/6611
(I'm going to talk about `Array` here, but the same argument can be made for `Range`. If `Array#bsearch_last` is acceptable, I will work also for `Range`.)
Ruby's bsearch returns the first element which satisfies the given block.
```ruby
# Search the first element greater than 18
array = [10, 15, 20, 25]
array.bsearch { |x| x > 18 } # => 20
```
If we want the last element, we need to invert the condition and step backward.
```ruby
# Search the last element less than 18
array = [10, 15, 20, 25]
index = array.bsearch_index { |x| !(x < 18) }
array[index-1] # => 15
```
Of course, we need to consider `nil` and the boundary.
```ruby
# Search the last element less than 100
index = array.bsearch_index { |x| !(x < 100) } # => nil
if index.nil?
array.last # => 25
else
array[index-1]
end
```
```ruby
# Search the last element less than 0
index = array.bsearch_index { |x| !(x < 0) } # => 0
if index.nil?
array.last
elsif index == 0
nil
else
array[index-1]
end
```
This is where mistakes can easily be made, so I propose `Array#bsearch_last` and `Array#bsearch_last_index`.
`Array#bsearch_last` returns the last element which satisfies the given block.
`Array#bsearch` requires that all false-evaluating elements precede all true-evaluating elements. As is clear from the meaning of the method, conversely to `bsearch`, `bsearch_last` requires that all true-evaluating elements precede all false-evaluating elements. (If `bsearch_last` is acceptable, the name "find-minimum mode" should be changed.)
```ruby
array = [10, 15, 20, 25]
array.bsearch_last { |x| x < 18 } # => 15
array.bsearch_last { |x| x < 100 } # => 25
array.bsearch_last { |x| x < 0 } # => nil
```
There are several possible options for find-any mode.
(1) `bsearch_last` does not support find-any mode.
A block for `bsearch_last` must return `true`, `false` or `nil`.
```
[1, 2, 3].bsearch_last { 0 } # => TypeError
```
My pull request tentatively includes this implementation.
(2) `bsearch_last` supports find-any mode and it behaves like `bsearch`.
`bsearch` with find-any mode returns an element, for which the block returns zero.
If multiple elements satisfy the condition, it is not determined which of them will be returned.
It is conceivable that `bsearch_last` behaves in the same way as `bsearch`.
```
# current behavior
# It is not specified whether `:b`, `:c`, or `:d` is returned.
[[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch { |a, b| 2 <=> a } # => [2, :c]
```
(3) `bsearch_last` supports find-any mode and returns the last element. Make `bsearch` return the first element.
Change the behavior of `bsearch` to return the first element for which the block returns zero.
`bsearch_last` returns the last element for which the block returns zero.
```
# Change it like this:
[[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch { |a, b| 2 <=> a } # => [2, :b]
[[1,:a], [2, :b], [2, :c], [2, :d], [3, :e]].bsearch_last { |a, b| 2 <=> a } # => [2, :d]
```
(If this option is adopted, the name "find-any mode" should be renamed.)
--
https://bugs.ruby-lang.org/
Issue #19873 has been reported by kjtsanaktsidis (KJ Tsanaktsidis).
----------------------------------------
Bug #19873: Thread#native_thread_id is incorrectly cached across fork on Linux
https://bugs.ruby-lang.org/issues/19873
* Author: kjtsanaktsidis (KJ Tsanaktsidis)
* Status: Open
* Priority: Normal
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
On Linux, when a process forks, the native thread ID of the (only) thread in the forked child should change.
```
>> libc = Fiddle.dlopen(nil)
=> #<Fiddle::Handle:0x0000ffffb0d8e900>
>> gettid = Fiddle::Function.new(libc['gettid'], [], Fiddle::TYPE_INT)
=>
#<Fiddle::Function:0x0000ffffb15d1130
...
>> gettid.call
=> 33
>> fork { puts gettid.call }; nil;
=> nil
36
```
However, the value of `Thread#native_thread_id` is (incorrectly) still set to the old value.
```
>> Thread.current.native_thread_id
=> 33
>> fork { puts Thread.current.native_thread_id }; nil;
=> nil
33
```
I think `#native_thread_id` should be re-fetched from the operating system via `gettid(2)` after fork.
--
https://bugs.ruby-lang.org/
Issue #19788 has been reported by thyresias (Thierry Lambert).
----------------------------------------
Bug #19788: Ripper returns a symbol instead of a token as operator for "::"
https://bugs.ruby-lang.org/issues/19788
* Author: thyresias (Thierry Lambert)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x64-mingw-ucrt]
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
```ruby
require 'ripper'
class BasicParser < Ripper
EVENTS.each do |event|
module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
def on_#{event}(*args)
puts "#{event}(\#{args.inspect})"
args.unshift :#{event}
args
end
RUBY
end
end
require 'pp'
BasicParser.new('a&.b').parse
# in stdout:
# ident(["a"])
# op(["&."])
# vcall([[:ident, "a"]])
# ident(["b"])
# call([[:vcall, [:ident, "a"]], [:op, "&."], [:ident, "b"]])
BasicParser.new('a::b').parse
# in stdout:
# ident(["a"])
# op(["::"])
# vcall([[:ident, "a"]])
# ident(["b"])
# call([[:vcall, [:ident, "a"]], :"::", [:ident, "b"]])
```
On the last line, consistent with `&.`, I would have expected:
```ruby
# call([[:vcall, [:ident, "a"]], [:op, "::"], [:ident, "b"]])
```
This is true for the "operator" argument of `call`, `command_call` and `field`.
Is it intended?
--
https://bugs.ruby-lang.org/