| Age | Commit message (Collapse) | Author |
|
Found when compiling ruby for windows-arm64 using msys2
Missing return type for function Init_lock_native_thread
lock_native_thread.c:45:1: error: type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int [-Wimplicit-int]
45 | Init_lock_native_thread(void)
| ^
| int
|
|
integers
(https://github.com/ruby/strscan/pull/89)
This commit adds `scan_byte` and `peek_byte`. `scan_byte` will scan the
current byte, return it as an integer, and advance the cursor.
`peek_byte` will return the current byte as an integer without advancing
the cursor.
Currently `StringScanner#get_byte` returns a string, but I want to get
the current byte without allocating a string. I think this will help
with writing high performance lexers.
---------
https://github.com/ruby/strscan/commit/873aba2e5d
Co-authored-by: Sutou Kouhei <kou@clear-code.com>
|
|
|
|
|
|
* Introduction of Happy Eyeballs Version 2 (RFC8305) in Socket.tcp
This is an implementation of Happy Eyeballs version 2 (RFC 8305) in Socket.tcp.
[Background]
Currently, `Socket.tcp` synchronously resolves names and makes connection attempts with `Addrinfo::foreach.`
This implementation has the following two problems.
1. In name resolution, the program stops until the DNS server responds to all DNS queries.
2. In a connection attempt, while an IP address is trying to connect to the destination host and is taking time, the program stops, and other resolved IP addresses cannot try to connect.
[Proposal]
"Happy Eyeballs" ([RFC 8305](https://datatracker.ietf.org/doc/html/rfc8305)) is an algorithm to solve this kind of problem. It avoids delays to the user whenever possible and also uses IPv6 preferentially.
I implemented it into `Socket.tcp` by using `Addrinfo.getaddrinfo` in each thread spawned per address family to resolve the hostname asynchronously, and using `Socket::connect_nonblock` to try to connect with multiple addrinfo in parallel.
[Outcome]
This change eliminates a fatal defect in the following cases.
Case 1. One of the A or AAAA DNS queries does not return
---
require 'socket'
class Addrinfo
class << self
# Current Socket.tcp depends on foreach
def foreach(nodename, service, family=nil, socktype=nil, protocol=nil, flags=nil, timeout: nil, &block)
getaddrinfo(nodename, service, Socket::AF_INET6, socktype, protocol, flags, timeout: timeout)
.concat(getaddrinfo(nodename, service, Socket::AF_INET, socktype, protocol, flags, timeout: timeout))
.each(&block)
end
def getaddrinfo(_, _, family, *_)
case family
when Socket::AF_INET6 then sleep
when Socket::AF_INET then [Addrinfo.tcp("127.0.0.1", 4567)]
end
end
end
end
Socket.tcp("localhost", 4567)
---
Because the current `Socket.tcp` cannot resolve IPv6 names, the program stops in this case. It cannot start to connect with IPv4 address.
Though `Socket.tcp` with HEv2 can promptly start a connection attempt with IPv4 address in this case.
Case 2. Server does not promptly return ack for syn of either IPv4 / IPv6 address family
---
require 'socket'
fork do
socket = Socket.new(Socket::AF_INET6, :STREAM)
socket.setsockopt(:SOCKET, :REUSEADDR, true)
socket.bind(Socket.pack_sockaddr_in(4567, '::1'))
sleep
socket.listen(1)
connection, _ = socket.accept
connection.close
socket.close
end
fork do
socket = Socket.new(Socket::AF_INET, :STREAM)
socket.setsockopt(:SOCKET, :REUSEADDR, true)
socket.bind(Socket.pack_sockaddr_in(4567, '127.0.0.1'))
socket.listen(1)
connection, _ = socket.accept
connection.close
socket.close
end
Socket.tcp("localhost", 4567)
---
The current `Socket.tcp` tries to connect serially, so when its first name resolves an IPv6 address and initiates a connection to an IPv6 server, this server does not return an ACK, and the program stops.
Though `Socket.tcp` with HEv2 starts to connect sequentially and in parallel so a connection can be established promptly at the socket that attempted to connect to the IPv4 server.
In exchange, the performance of `Socket.tcp` with HEv2 will be degraded.
---
100.times { Socket.tcp("www.ruby-lang.org", 80) }
---
This is due to the addition of the creation of IO objects, Thread objects, etc., and calls to `IO::select` in the implementation.
* Avoid NameError of Socket::EAI_ADDRFAMILY in MinGW
* Support Windows with SO_CONNECT_TIME
* Improve performance
I have additionally implemented the following patterns:
- If the host is single-stack, name resolution is performed in the main thread. This reduces the cost of creating threads.
- If an IP address is specified, name resolution is performed in the main thread. This also reduces the cost of creating threads.
- If only one IP address is resolved, connect is executed in blocking mode. This reduces the cost of calling IO::select.
Also, I have added a fast_fallback option for users who wish not to use HE.
Here are the results of each performance test.
```ruby
require 'socket'
require 'benchmark'
HOSTNAME = "www.ruby-lang.org"
PORT = 80
ai = Addrinfo.tcp(HOSTNAME, PORT)
Benchmark.bmbm do |x|
x.report("Domain name") do
30.times { Socket.tcp(HOSTNAME, PORT).close }
end
x.report("IP Address") do
30.times { Socket.tcp(ai.ip_address, PORT).close }
end
x.report("fast_fallback: false") do
30.times { Socket.tcp(HOSTNAME, PORT, fast_fallback: false).close }
end
end
```
```
user system total real
Domain name 0.015567 0.032511 0.048078 ( 0.325284)
IP Address 0.004458 0.014219 0.018677 ( 0.284361)
fast_fallback: false 0.005869 0.021511 0.027380 ( 0.321891)
````
And this is the measurement result when executed in a single stack environment.
```
user system total real
Domain name 0.007062 0.019276 0.026338 ( 1.905775)
IP Address 0.004527 0.012176 0.016703 ( 3.051192)
fast_fallback: false 0.005546 0.019426 0.024972 ( 1.775798)
```
The following is the result of the run on Ruby 3.3.0.
(on Dual stack environment)
```
user system total real
Ruby 3.3.0 0.007271 0.027410 0.034681 ( 0.472510)
```
(on Single stack environment)
```
user system total real
Ruby 3.3.0 0.005353 0.018898 0.024251 ( 1.774535)
```
* Do not cache `Socket.ip_address_list`
As mentioned in the comment at https://github.com/ruby/ruby/pull/9374#discussion_r1482269186, caching Socket.ip_address_list does not follow changes in network configuration.
But if we stop caching, it becomes necessary to check every time `Socket.tcp` is called whether it's a single stack or not, which could further degrade performance in the case of a dual stack.
From this, I've changed the approach so that when a domain name is passed, it doesn't check whether it's a single stack or not and resolves names in parallel each time.
The performance measurement results are as follows.
require 'socket'
require 'benchmark'
HOSTNAME = "www.ruby-lang.org"
PORT = 80
ai = Addrinfo.tcp(HOSTNAME, PORT)
Benchmark.bmbm do |x|
x.report("Domain name") do
30.times { Socket.tcp(HOSTNAME, PORT).close }
end
x.report("IP Address") do
30.times { Socket.tcp(ai.ip_address, PORT).close }
end
x.report("fast_fallback: false") do
30.times { Socket.tcp(HOSTNAME, PORT, fast_fallback: false).close }
end
end
user system total real
Domain name 0.004085 0.011873 0.015958 ( 0.330097)
IP Address 0.000993 0.004400 0.005393 ( 0.257286)
fast_fallback: false 0.001348 0.008266 0.009614 ( 0.298626)
* Wait forever if fallback addresses are unresolved, unless resolv_timeout
Changed from waiting only 3 seconds for name resolution when there is no fallback address available, to waiting as long as there is no resolv_timeout.
This is in accordance with the current `Socket.tcp` specification.
* Use exact pattern to match IPv6 address format for specify address family
|
|
rb_str_locktmp_ensure is a private API.
|
|
rb_fstring is a private API, so we should use rb_str_to_interned_str
instead, which is a public API.
|
|
Signed-off-by: Marek Küthe <m.k@mk16.de>
|
|
Signed-off-by: Marek Küthe <m.k@mk16.de>
|
|
Using RHASH_TBL_RAW is a private API, so we should use rb_hash_foreach
rather than RHASH_TBL_RAW with st_foreach.
|
|
Using RHASH_TBL_RAW is a private API, so we should use rb_hash_foreach
rather than RHASH_TBL_RAW with st_foreach.
|
|
Only consider it eof if we read ahead and something fills the buf.
If not, we may only have empty blocks and the footer.
Fixes https://github.com/ruby/zlib/pull/56
https://github.com/ruby/zlib/commit/437bea8003
|
|
It's been 2 years since ruby/date#49, so it's okay.
https://github.com/ruby/date/commit/435dfec6c8
|
|
Introduce `rb_thread_lock_native_thread()` to allocate dedicated
native thread to the current Ruby thread for M:N threads.
This C API is similar to Go's `runtime.LockOSThread()`.
Accepted at https://github.com/ruby/dev-meeting-log/blob/master/2023/DevMeeting-2023-08-24.md
(and missed to implement on Ruby 3.3.0)
|
|
|
|
Introduce another semantic value stack for Ripper so that
Ripper can manage both Node and Ruby Object separately.
This rearchitectutre of Ripper solves these issues.
Therefore adding test cases for them.
* [Bug 10436] https://bugs.ruby-lang.org/issues/10436
* [Bug 18988] https://bugs.ruby-lang.org/issues/18988
* [Bug 20055] https://bugs.ruby-lang.org/issues/20055
Checked the differences of `Ripper.sexp` for files under `/test/ruby`
are only on test_pattern_matching.rb.
The differences comes from the differences between
`new_hash_pattern_tail` functions between parser and Ripper.
Ripper `new_hash_pattern_tail` didn’t call `assignable` then
`kw_rest_arg` wasn’t marked as local variable.
This is also fixed by this commit.
```
--- a/./tmp/before/test_pattern_matching.rb
+++ b/./tmp/after/test_pattern_matching.rb
@@ -3607,7 +3607,7 @@
[:in,
[:hshptn, nil, [], [:var_field, [:@ident, “a”, [984, 13]]]],
[[:binary,
- [:vcall, [:@ident, “a”, [985, 10]]],
+ [:var_ref, [:@ident, “a”, [985, 10]]],
:==,
[:hash, nil]]],
nil]]],
@@ -3662,7 +3662,7 @@
[:in,
[:hshptn, nil, [], [:var_field, [:@ident, “a”, [993, 13]]]],
[[:binary,
- [:vcall, [:@ident, “a”, [994, 10]]],
+ [:var_ref, [:@ident, “a”, [994, 10]]],
:==,
[:hash,
[:assoclist_from_args,
@@ -3813,7 +3813,7 @@
[:command,
[:@ident, “raise”, [1022, 10]],
[:args_add_block,
- [[:vcall, [:@ident, “b”, [1022, 16]]]],
+ [[:var_ref, [:@ident, “b”, [1022, 16]]]],
false]]],
[:else, [[:var_ref, [:@kw, “true”, [1024, 10]]]]]]]],
nil,
@@ -3876,7 +3876,7 @@
[:@int, “0”, [1033, 15]]],
:“&&“,
[:binary,
- [:vcall, [:@ident, “b”, [1033, 20]]],
+ [:var_ref, [:@ident, “b”, [1033, 20]]],
:==,
[:hash, nil]]]],
nil]]],
@@ -3946,7 +3946,7 @@
[:@int, “0”, [1042, 15]]],
:“&&“,
[:binary,
- [:vcall, [:@ident, “b”, [1042, 20]]],
+ [:var_ref, [:@ident, “b”, [1042, 20]]],
:==,
[:hash,
[:assoclist_from_args,
@@ -5206,7 +5206,7 @@
[[:assoc_new,
[:@label, “c:“, [1352, 22]],
[:@int, “0”, [1352, 25]]]]]],
- [:vcall, [:@ident, “r”, [1352, 29]]]],
+ [:var_ref, [:@ident, “r”, [1352, 29]]]],
false]]],
[:binary,
[:call,
@@ -5299,7 +5299,7 @@
[:assoc_new,
[:@label, “c:“, [1367, 34]],
[:@int, “0”, [1367, 37]]]]]],
- [:vcall, [:@ident, “r”, [1367, 41]]]],
+ [:var_ref, [:@ident, “r”, [1367, 41]]]],
false]]],
[:binary,
[:call,
@@ -5931,7 +5931,7 @@
[:in,
[:hshptn, nil, [], [:var_field, [:@ident, “r”, [1533, 11]]]],
[[:binary,
- [:vcall, [:@ident, “r”, [1534, 8]]],
+ [:var_ref, [:@ident, “r”, [1534, 8]]],
:==,
[:hash,
[:assoclist_from_args,
```
|
|
[Feature #16495]
|
|
https://github.com/ruby/strscan/commit/ba338b882c
|
|
https://github.com/ruby/strscan/commit/842845af1f
|
|
(https://github.com/ruby/fiddle/pull/138)
See https://guides.rubygems.org/specification-reference/#metadata for changelog_uri metadata.
https://github.com/ruby/fiddle/commit/0bd8e96adc
|
|
The extension library has each initialization function named "Init_" +
basename. If multiple extensions have the same base name (such as
cgi/escape and erb/escape), the same function will be registered for
both names.
To fix this conflict, rename the initialization functions under sub
directories using using parent names, when statically linking.
|
|
|
|
When ripping the base directory off the result names.
|
|
This reverts commit 673ed41c81cf5a6951bcb2c3dec82d7bd6ea7440.
|
|
https://github.com/flori/json/commit/202ffe2335
|
|
'!' suffix is needed for event dispatch.
|
|
https://github.com/ruby/win32ole/commit/57e4a38465
|
|
https://github.com/ruby/win32ole/commit/78ff137c0f
|
|
https://github.com/ruby/win32ole/commit/70ea60c4d2
|
|
https://github.com/ruby/win32ole/commit/7648ee7e56
|
|
https://github.com/ruby/win32ole/commit/1c95816168
|
|
https://github.com/ruby/win32ole/commit/2f51493bd1
|
|
https://github.com/ruby/win32ole/commit/2c5d193da7
|
|
https://github.com/ruby/win32ole/commit/5feede2cc5
|
|
Prevent name clash with `WIN32OLE::Variant`, of generated document
files on case-insensitive filesystems, such as Windows.
https://github.com/ruby/win32ole/commit/049e5f0a6e
|
|
Since RDoc searches `var = rb_define_class_under(...)` statements
literally, they cannot be built by macros.
https://github.com/ruby/digest/commit/d39b684f91
|
|
https://github.com/ruby/digest/commit/e5d30394b3
|
|
https://github.com/ruby/digest/commit/6db96aa99a
|
|
|
|
This commit changes `struct parser_params` lastline and nextline
from `VALUE` (String object) to `rb_parser_string_t *` so that
dependency on Ruby Object is reduced.
`parser_string_buffer_t string_buffer` is added to `struct parser_params`
to manage `rb_parser_string_t` pointers of each line. All allocated line
strings are freed in `rb_ruby_parser_free`.
|
|
|
|
|
|
In case of EAI_SYSTEM, getaddrinfo is supposed to set more detail in
errno; however, because we call getaddrinfo on a thread now, and errno
is threadlocal, that information is being lost. Instead, we just raise
whatever errno happens to be on the calling thread (which can be
something very confusing, like `ECHILD`).
Fix it by explicitly propagating errno back to the calling thread
through the getaddrinfo_arg structure.
[Bug #20198]
|
|
https://github.com/ruby/nkf/commit/65506fecfd
|
|
https://github.com/ruby/nkf/commit/19df7138f7
|
|
This pulls in the nkf extension implementation from JRuby. The
build and load logic has been updated along the same lines as
ruby/digest and the gem appears to build correctly for the -java
platform.
Fixes https://github.com/ruby/nkf/pull/13
https://github.com/ruby/nkf/commit/18f57f36ed
|
|
xfree can handle null values, so we don't need to check it.
|
|
https://github.com/ruby/strscan/commit/d6f97ec102
|
|
ASAN leaves a pointer to the fake frame on the stack; we can use the
__asan_addr_is_in_fake_stack API to work out the extent of the fake
stack and thus mark any VALUEs contained therein.
[Bug #20001]
|
|
for dumping
https://github.com/ruby/psych/commit/3d051d89aa
|