`rb_jmpbuf_t` type is considerably large due to inline-allocated
Asyncify buffer, and it leads to stack overflow even with small number
of C-method call frames. This commit allocates the Asyncify buffer used
by `rb_wasm_setjmp` in heap to mitigate the issue.
This patch introduces a new type `rb_vm_tag_jmpbuf_t` to abstract the
representation of a jump buffer, and init/deinit hook points to manage
lifetime of the buffer. These changes are effectively NFC for non-wasm
platforms.
Context: https://github.com/ivoanjo/gvl-tracing/pull/4
Some hooks may want to collect data on a per thread basis.
Right now the only way to identify the concerned thread is to
use `rb_nativethread_self()` or similar, but even then because
of the thread cache or MaNy, two distinct Ruby threads may report
the same native thread id.
By passing `thread->self`, hooks can use it as a key to store
the metadata.
NB: Most hooks are executed outside the GVL, so such data collection
need to use a thread-safe data-structure, and shouldn't use the
reference in other ways from inside the hook.
They must also either pin that value or handle compaction.
Resetting `@default_specifications_dir` to `nil` means that the
`Gem.default_specifications_dir` needs to be invoked. However, given
that this method might be overridden by operating_system.rb and similar,
this might lead to various test failures. Providing the default value
makes the issues go away.
https://github.com/rubygems/rubygems/commit/59626cb650
Original output:
~~~
Failure: test_realworld_upgraded_default_gem(TestGemRequire): <false> is not true.
/mnt/test/rubygems/test_require.rb:474:in `test_realworld_upgraded_default_gem'
471: File.write(path, code)
472:
473: output = Gem::Util.popen({ "GEM_HOME" => @gemhome }, *ruby_with_rubygems_in_load_path, path).strip
=> 474: assert $?.success?
475: refute_empty output
476: assert_equal "999.99.9", output.lines[0].chomp
477: # Make sure only files from the newer json gem are loaded, and no files from the default json gem
~~~
New output:
~~~
Failure: test_realworld_upgraded_default_gem(TestGemRequire)
/mnt/test/rubygems/test_require.rb:475:in `test_realworld_upgraded_default_gem'
472:
473: output = Gem::Util.popen({ "GEM_HOME" => @gemhome }, *ruby_with_rubygems_in_load_path, path).strip
474: refute_empty output
=> 475: assert_equal "999.99.9", output.lines[0].chomp
476: # Make sure only files from the newer json gem are loaded, and no files from the default json gem
477: assert_equal ["#{@gemhome}/gems/json-999.99.9/lib/json.rb"], output.lines.grep(%r{/gems/json-}).map(&:chomp)
478: assert $?.success?
<"999.99.9"> expected but was
<"/mnt/tmp/test_rubygems_20231110-36663-of405r/test_realworld_upgraded_default_gem.rb:3:in `<main>': undefined method `version' for nil:NilClass (NoMethodError)">
diff:
? 999 .99.9
? /mnt/tmp/test_rubygems_20231110-36663-of405r/test_realworld_upgraded_default_gem rb:3:in `<main>': undefined method `version' for nil:NilClass (NoMethodError)
? ??? ????
~~~
It is more valuable to check the command output then the error code. If
the command fails for some reason, the output probably contains some
detail, while checking the return code tells not much.
https://github.com/rubygems/rubygems/commit/b76062e852
If a Gemfile duplicates a development dependency also defined in a local
gemspec with a different requirement, the requirement in the local
gemspec will be silently ignored.
This surprised me.
I think we should either:
* Make sure both requirements are considered, like it happens for
runtime dependencies (I added a spec to illustrate the current behavior
here).
* Add a warning that the requirement in the gemspec will be ignored.
I think the former is slightly preferable, but it may cause some
bundle's that previously resolve to no longer resolver.
I went with the latter but the more I think about it, the more this
seems like it should behave like the former.
https://github.com/rubygems/rubygems/commit/ad6843972f
Since we started locking the specific platform in the lockfile, that has
created an annoying situation for users that don't develop on Linux.
They will create a lockfile on their machines, locking their local
platform, for example, darwin. But then that lockfile won't work
automatically when deploying to Heroku for example, because the lockfile
is frozen and the Linux platform is not included.
There's the chance though that resolving against two platforms (Linux +
the local platform) won't succeed while resolving for just the current
platform will. So, instead, we check other platform specific variants
available for the resolution we initially found, and lock those
platforms and specs too if they satisfy the resolution.
This is only done when generating new lockfiles from scratch, existing
lockfiles should keep working as before, and it's only done for "ruby
platforms", i.e., not Java or Windows which have their own complexities,
and so are excluded.
With this change, we expect that MacOS users can bundle locally and
deploy to Heroku without needing to do anything special.
https://github.com/rubygems/rubygems/commit/5f24f06bc5
Originally, the failed test case reported following error:
~~~
Failure: test_gem_exec_gem_uninstall(TestGemCommandsExecCommand):
<""> was expected to include
<"Successfully uninstalled a-2\n">.
/mnt/test/rubygems/test_gem_commands_exec_command.rb:742:in `block in test_gem_exec_gem_uninstall'
739:
740: # assert_empty @ui.error
741: refute_includes @ui.output, "running gem exec with"
=> 742: assert_includes @ui.output, "Successfully uninstalled a-2\n"
743:
744: invoke "--verbose", "gem", "uninstall", "b"
745: assert_includes @ui.output, "Successfully uninstalled b-2\n"
/mnt/lib/rubygems/user_interaction.rb:46:in `use_ui'
/mnt/lib/rubygems/user_interaction.rb:69:in `use_ui'
/mnt/test/rubygems/test_gem_commands_exec_command.rb:726:in `test_gem_exec_gem_uninstall'
~~~
This does not tell much. Empty string is more often good sign, but not
in this case. However, checking error output first helps with
understanding possible issue:
~~~
Failure: test_gem_exec_gem_uninstall(TestGemCommandsExecCommand):
<"ERROR: While executing gem ... (Gem::FilePermissionError)\n" +
" You don't have write permissions for the /builddir/bin directory.\n" +
"\t/mnt/lib/rubygems/uninstaller.rb:213:in `remove_executables'\n" +
... snip ...
/mnt/test/rubygems/test_gem_commands_exec_command.rb:740:in `block in test_gem_exec_gem_uninstall'
737: nil
738: end
739:
=> 740: assert_empty @ui.error
741: refute_includes @ui.output, "running gem exec with"
742: assert_includes @ui.output, "Successfully uninstalled a-2\n"
743:
/mnt/lib/rubygems/user_interaction.rb:46:in `use_ui'
/mnt/lib/rubygems/user_interaction.rb:69:in `use_ui'
/mnt/test/rubygems/test_gem_commands_exec_command.rb:726:in `test_gem_exec_gem_uninstall'
~~~
BTW this issue is caused by operating_system.rb overriding
`Gem.operating_system_defaults` method and explicitly adding `--bindir`
option.
https://github.com/rubygems/rubygems/commit/d98e36bbe7
Since the callback defined in the objspace module might give up the GVL,
we need to make sure the right cr->mfd value is set back after the GVL
is re-obtained.
* Weaken notice about API stability. A few public APIs in here now.
* Prune out APIs from the docs that are private in nature
* Enable markdown mode and ensure `--` options are quoted so they are
rendered as two dashes in the HTML.