Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Isolate v8 symbols #179

Merged
merged 6 commits into from
Oct 9, 2020
Merged

Conversation

lloeki
Copy link
Collaborator

@lloeki lloeki commented Oct 5, 2020

Hello!

We identified an issue happening when two extensions are built with different V8 versions, then loaded at the same time.

In an ideal world, all extensions would be built with -fvisibility=hidden, only exposing relevant symbols and avoiding clases, unfortunately that is not the case.

Indeed the libv8 gem does not build its static library with -fvisibility=hidden. The result is that when this static library is linked into a Ruby extension (IOW a dynamic library), V8 symbols are global, irrespective of passing -fvisibility=hidden when building the extension.

Additionally, Ruby doesn't really make an effort to load its extensions in isolated ways, resulting in the default of globally available symbols.

As a result, the second extension being loaded will resolve some of its V8 symbols to the first ones that were loaded.

To combat this, within Sqreen's fork of MiniRacer, we created a small wrapper that takes in charge loading the extension more privately by:

  • enforcing all symbols to be local (via RTLD_LOCAL), preventing other libs to pick its symbols up
  • attempting to enforce binding to local symbols first (via RTLD_DEEPBIND), preventing this lib to pick others symbols

Unfortunately, the latter is not always available, resulting in MiniRacer's V8 symbols being picked up by other libraries, even when they use RTLD_LOCAL (which only controls things one way). In that case we are left with no option.

This PR attempts to make MiniRacer a good citizen in two ways:

  • first commit: compile with -fvisibility=hidden to hide any irrelevant mini_racer_extension symbols, and be ready if/when libv8_monolith.a is compiled with it too.
  • second commit: hide V8 symbols from libv8_monolith.a that wasn't built with -fvisibility=hidden.

Considered alternatives

  • linker version scripts to hide symbols, but it's only supported by GCC's ld
  • -exported_symbols_list and -unexported_symbols_list, but it needs exhaustive generation of symbols to hide and show. Possible, but calling into nm libv8_monolith.a and parsing the output to generate the list could be unreliable.
  • leveraging gem dependencies to ensure the same libv8 version and build: unfortunately this does not mean a given lib wasn't built with a different v8, unless all gems pin their libv8 versions exactly in their gemspec (this particular one stumped us for a long time)

Excerpt of mini_racer_extension.bundle symbol table (T means global, t means local`):

$ nm -C lib/mini_racer_extension.bundle | grep ' T' | head
0000000000003ce0 T _Init_mini_racer_extension
00000000001544b0 T _v8_internal_Get_Object(void*)
0000000000154870 T _v8_internal_Node_Print(void*)
0000000000154550 T _v8_internal_Print_Code(void*)
00000000001544f0 T _v8_internal_Print_Object(void*)
00000000001547c0 T _v8_internal_Print_StackTrace()
0000000000154800 T _v8_internal_Print_TransitionTree(void*)
0000000000154730 T _v8_internal_Print_LayoutDescriptor(void*)
000000000000f260 T V8_Fatal(char const*, ...)
000000000000f3b0 T V8_Dcheck(char const*, int, char const*)

Excerpt of a stack trace where code jumps from one lib to the other within libv8:

-- C level backtrace information -------------------------------------------
/Users/lloeki/.rubies/ruby-2.7.1/bin/ruby(rb_vm_bugreport+0x96) [0x106ebf616]
/Users/lloeki/.rubies/ruby-2.7.1/bin/ruby(rb_bug_for_fatal_signal+0x1d0) [0x106cf9270]
/Users/lloeki/.rubies/ruby-2.7.1/bin/ruby(sigsegv+0x5b) [0x106e22c4b]
/usr/lib/system/libsystem_platform.dylib(_sigtramp+0x1d) [0x7fff7248c5fd]
/Users/lloeki/.gem/ruby/2.7.1/gems/mini_racer-0.3.1/lib/mini_racer_extension.bundle(_ZN2v88internal12_GLOBAL__N_123GetPageTableInitializerEv+0x25) [0x10bade405]
/Users/lloeki/.gem/ruby/2.7.1/gems/mini_racer-0.3.1/lib/mini_racer_extension.bundle(0x10badea39) [0x10badea39]
/Users/lloeki/.gem/ruby/2.7.1/gems/mini_racer-0.3.1/lib/mini_racer_extension.bundle(0x10b77b3b6) [0x10b77b3b6]
/Users/lloeki/.gem/ruby/2.7.1/gems/mini_racer-0.3.1/lib/mini_racer_extension.bundle(0x10b77bc5e) [0x10b77bc5e]
/Users/lloeki/Workspace/github.com/sqreen/mini_racer/lib/sq_mini_racer_extension.bundle(_ZN2v88internal9SemiSpace6CommitEv+0x7a) [0x10d81df5a]
/Users/lloeki/Workspace/github.com/sqreen/mini_racer/lib/sq_mini_racer_extension.bundle(0x10d81de76) [0x10d81de76]
/Users/lloeki/Workspace/github.com/sqreen/mini_racer/lib/sq_mini_racer_extension.bundle(0x10d7a35ef) [0x10d7a35ef]
/Users/lloeki/Workspace/github.com/sqreen/mini_racer/lib/sq_mini_racer_extension.bundle(0x10d74cf00) [0x10d74cf00]
/Users/lloeki/Workspace/github.com/sqreen/mini_racer/lib/sq_mini_racer_extension.bundle(0x10d74c9fd) [0x10d74c9fd]
/Users/lloeki/Workspace/github.com/sqreen/mini_racer/lib/sq_mini_racer_extension.bundle(0x10d5e78fb) [0x10d5e78fb]
/Users/lloeki/Workspace/github.com/sqreen/mini_racer/lib/sq_mini_racer_extension.bundle(0x10d5e79af) [0x10d5e79af]
/Users/lloeki/Workspace/github.com/sqreen/mini_racer/lib/sq_mini_racer_extension.bundle(_ZN11IsolateInfo4initEP12SnapshotInfo+0xc2) [0x10d3ba012]
/Users/lloeki/Workspace/github.com/sqreen/mini_racer/lib/sq_mini_racer_extension.bundle(_ZL22rb_context_init_unsafemmm+0x126) [0x10d3bc016]
/Users/lloeki/.rubies/ruby-2.7.1/bin/ruby(vm_call_cfunc+0x16c) [0x106eb0cdc]
/Users/lloeki/.rubies/ruby-2.7.1/bin/ruby(vm_exec_core+0x38b0) [0x106e97050]

@lloeki lloeki force-pushed the fix/isolate-v8-symbols branch from 858a10e to 75de2be Compare October 5, 2020 16:23
@SamSaffron
Copy link
Collaborator

Overall I like this, is there any impact to load time of the library?

Additionally are we blocked here on a libv8 change? Is there a PR we need to amend it?

@lloeki lloeki force-pushed the fix/isolate-v8-symbols branch from 75de2be to 1aa06eb Compare October 6, 2020 08:26
@lloeki
Copy link
Collaborator Author

lloeki commented Oct 6, 2020

Overall I like this, is there any impact to load time of the library?

With RTLD_NOW, a theoretical one, albeit small. I changed it to RTLD_LAZY in an attempt to fix Travis CI breaking on Linux, which also spreads it (possibly reducing it overall if some symbols are never used). There's the $LOAD_PATH lookup too, quite similar to what an additional require does.

I'm looking into the CI break. We've had this working for a while on Linux (including with musl) so I'm not yet sure what the issue is:

/home/travis/build/rubyjs/mini_racer/lib/mini_racer.rb:8:in `load': /home/travis/build/rubyjs/mini_racer/lib/mini_racer_extension.so: undefined symbol: _ZTTNSt7__cxx1119basic_istringstreamIcSt11char_traitsIcESaIcEEE (LoadError)

Additionally are we blocked here on a libv8 change?

With the loader, we're not. In the future, if (when?) libv8 manages to be built with -fvisibility-hidden (or something to that effect), we could drop the loader.

Is there a PR we need to amend it?

I'm currently trying to find a simple way to have libv8_monolith.a built with local symbols and plan to open a PR there.

lloeki added 3 commits October 7, 2020 17:13
This Dockerfile makes use of caching and invalidation to save time
between retries.

This drops you in a IRB shell with mini_racer required already:

    docker build -t mini_racer .
    docker run --rm -it mini_racer

A single command for repeated runs:

    docker build -t mini_racer . && \
      docker run --rm -it mini_racer bundle exec rake test

It's possible to specify the Ruby version to build upon:

    docker build --build-arg RUBY_VERSION=2.6 -t mini_racer . && \
      docker run --rm -it mini_racer bundle exec rake test
@lloeki
Copy link
Collaborator Author

lloeki commented Oct 7, 2020

Seems like the issue with _ZTTNSt7__cxx1119basic_istringstreamIcSt11char_traitsIcESaIcEEE a.k.a VTT for std::__cxx11::basic_istringstream<char, std::char_traits<char>, std::allocator<char> > is unrelated to this PR:

  • Those two other PR's jobs failed for similar reasons
  • I cannot reproduce it on the official ruby:2.7 image

https://travis-ci.org/github/rubyjs/mini_racer/jobs/714390184

https://travis-ci.org/github/rubyjs/mini_racer/jobs/732159781

@lloeki
Copy link
Collaborator Author

lloeki commented Oct 7, 2020

I took on myself to add a Dockerfile (and .dockerignore) to this PR for easy and consistent reproduction with the following command. So as not to block this one I can move it to another PR or altogether remove it though, as you prefer.

docker build -t mini_racer . && docker run --rm -it mini_racer bundle exec rake test
docker build --build-arg RUBY_VERSION=2.6 -t mini_racer . && docker run --rm -it mini_racer bundle exec rake test

@SamSaffron
Copy link
Collaborator

There has been a lot complaints over the past few months regarding mini_racer builds failing on old versions of gcc. I strongly suspect this is all somewhat related.

@SamSaffron
Copy link
Collaborator

SamSaffron commented Oct 8, 2020

I am fine to merge this, but can you confirm this is going to work on MacOS as well (I can see you allowed for it)

Another huge one I would love some help on is:

https://chromium-review.googlesource.com/c/v8/v8/+/2416501

This will be enormously useful (especially for sqreen) cause if we have a switch for single threaded mode you could use it and not need to worry about processes forking anymore and breaking the runtime.

Would you like to take lead on this? V8 team are waiting on feedback.

@lloeki
Copy link
Collaborator Author

lloeki commented Oct 8, 2020

Another huge one I would love some help on is

Is this tied to this issue and that commit?

This will be enormously useful (especially for sqreen) cause if we have a switch for single threaded mode you could use it and not need to worry about processes forking anymore and breaking the runtime.

As it turns out I just happen to have a customer who's using the parallel gem (in some yet to be determined way, but it appears to fork so probably not threaded mode) and recently complaining that our V8 isolates crash his app.

I cannot commit on a timeline but this definitely looks worth a shot. I'll bring this up to the team.

@lloeki
Copy link
Collaborator Author

lloeki commented Oct 8, 2020

can you confirm this is going to work on MacOS as well (I can see you allowed for it)

Yes, this works on macOS (incidentally I work on macOS first and test on Linux later).

@SamSaffron
Copy link
Collaborator

Cool, let try this out then! Thanks @lloeki .

@SamSaffron SamSaffron merged commit c79ff23 into rubyjs:master Oct 9, 2020
@cataphract cataphract deleted the fix/isolate-v8-symbols branch December 9, 2020 10:40
ivoanjo added a commit to DataDog/dd-trace-rb that referenced this pull request May 6, 2022
When Ruby loads a native extension (using `require`), it uses
`dlopen(..., RTLD_LAZY | RTLD_GLOBAL)`
(https://github.com/ruby/ruby/blob/67950a4c0a884bdb78d9beb4405ebf7459229b21/dln.c#L362).

This means that every symbol exposed directly or indirectly by that native
extension becomes visible to every other extension in the Ruby process. This can
cause issues, see rubyjs/mini_racer#179.

Ruby's extension loading mechanism is not configurable -- there's no way to tell
it to use different flags when calling `dlopen`. To get around this, this
commit introduces introduces another extension (profiling loader) which has only
a single responsibility: mimic Ruby's extension loading mechanism, but when
calling  `dlopen` use a different set of flags.

This idea was shamelessly stolen from @lloeki's work in
rubyjs/mini_racer#179, big thanks!

Note that, that we know of, the profiling native extension only exposes one
potentially problematic symbol: `rust_eh_personality`
(coming from libddprof/libdatadog).

Future versions of Rust have been patched not to expose this
(see rust-lang/rust#95604 (comment)) so we
may want to revisit the need for this loader in the future, and perhaps delete
it if we no longer require its services :)

Testing the `ddtrace_profiling_loader.c`'s failure handling paths is a bit
non-trivial, so here's how I did it manually (some logs abridged):

```bash
 # 1️⃣  Validate everything's working fine:

 $ ruby -v
 ruby 2.7.6p219 (2022-04-12 revision c9c2245c0a) [x86_64-darwin20]
 $ bundle rake clean compile
 ...
 $ DD_TRACE_DEBUG=true DD_PROFILING_ENABLED=true bundle exec ddtracerb exec ruby -e 'nil'
 D, [2022-05-06T12:17:41.554770 #19686] DEBUG -- ddtrace: [ddtrace]
 (/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/core/configuration/components.rb:340:in `startup!') Profiling started'

 # 2️⃣  Force library load failure:

 # (Delete the library version for the Ruby I'm using)
 $ rm lib/ddtrace_profiling_native_extension.2.7.6_x86_64-darwin20.bundle
 $ DD_TRACE_DEBUG=true DD_PROFILING_ENABLED=true bundle exec ddtracerb exec ruby -e 'nil'
 W, [2022-05-06T12:19:23.891711 #21159]  WARN -- ddtrace: [ddtrace]
 (/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/core/configuration/components.rb:345:in `startup!')
 Profiling was requested but is not supported, profiling disabled: There was an error loading the profiling native extension due to
 'Failure to load ddtrace_profiling_native_extension.2.7.6_x86_64-darwin20 due to
 dlopen(/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/profiling/../../ddtrace_profiling_native_extension.2.7.6_x86_64-darwin20.bundle, 5):
 image not found' at '/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/profiling/load_native_extension.rb:22:in `<top (required)>''

 # 3️⃣  Force a library incompatibility:

 # (Copy library compiled with a different Ruby version)
 $ cp lib/ddtrace_profiling_native_extension.3.2.0_x86_64-darwin20.bundle lib/ddtrace_profiling_native_extension.2.7.6_x86_64-darwin20.bundle
 $ DD_TRACE_DEBUG=true DD_PROFILING_ENABLED=true bundle exec ddtracerb exec ruby -e 'nil'
 W, [2022-05-06T12:22:24.036956 #21773]  WARN -- ddtrace: [ddtrace]
 (/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/core/configuration/components.rb:345:in `startup!')
 Profiling was requested but is not supported, profiling disabled: There was an error loading the profiling native extension due to
 Failure to load ddtrace_profiling_native_extension.2.7.6_x86_64-darwin20 due to library was compiled and linked to a different Ruby version'
 at '/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/profiling/load_native_extension.rb:22:in `<top (required)>'

 # 4️⃣  Force an initialization failure:

 # (Restore library clobbered in previous steps)
 $ bundle rake clean compile
 ...
 # (Rename expected initialization function)
 $ git diff -U0 lib/datadog/profiling/load_native_extension.rb
 diff --git a/lib/datadog/profiling/load_native_extension.rb b/lib/datadog/profiling/load_native_extension.rb
 index 5ea4bb32c..af964bade 100644
 --- a/lib/datadog/profiling/load_native_extension.rb
 +++ b/lib/datadog/profiling/load_native_extension.rb
 @@ -18 +18 @@ full_file_path = "#{__dir__}/../../#{extension_name}.#{RbConfig::CONFIG['DLEXT']
 -init_function_name = "Init_#{extension_name.split('.').first}"
 +init_function_name = "Init_#{extension_name.split('.').first}_kaboom
 $ DD_TRACE_DEBUG=true DD_PROFILING_ENABLED=true bundle exec ddtracerb exec ruby -e 'nil'
 W, [2022-05-06T12:27:55.706221 #23036]  WARN -- ddtrace: [ddtrace]
 (/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/core/configuration/components.rb:345:in `startup!')
 Profiling was requested but is not supported, profiling disabled: There was an error loading the profiling native extension due to
 'Failure to load ddtrace_profiling_native_extension.2.7.6_x86_64-darwin20 due to dlsym(0x7fe144151630,
   Init_ddtrace_profiling_native_extension_kaboom): symbol not found' at
 '/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/profiling/load_native_extension.rb:22:in `<top (required)>''
```
ivoanjo added a commit to DataDog/dd-trace-rb that referenced this pull request May 6, 2022
When Ruby loads a native extension (using `require`), it uses
`dlopen(..., RTLD_LAZY | RTLD_GLOBAL)`
(https://github.com/ruby/ruby/blob/67950a4c0a884bdb78d9beb4405ebf7459229b21/dln.c#L362).

This means that every symbol exposed directly or indirectly by that native
extension becomes visible to every other extension in the Ruby process. This can
cause issues, see rubyjs/mini_racer#179.

Ruby's extension loading mechanism is not configurable -- there's no way to tell
it to use different flags when calling `dlopen`. To get around this, this
commit introduces introduces another extension (profiling loader) which has only
a single responsibility: mimic Ruby's extension loading mechanism, but when
calling  `dlopen` use a different set of flags.

This idea was shamelessly stolen from @lloeki's work in
rubyjs/mini_racer#179, big thanks!

Note that, that we know of, the profiling native extension only exposes one
potentially problematic symbol: `rust_eh_personality`
(coming from libddprof/libdatadog).

Future versions of Rust have been patched not to expose this
(see rust-lang/rust#95604 (comment)) so we
may want to revisit the need for this loader in the future, and perhaps delete
it if we no longer require its services :)

Testing the `ddtrace_profiling_loader.c`'s failure handling paths is a bit
non-trivial, so here's how I did it manually (some logs abridged):

```bash
 # 1️⃣  Validate everything's working fine:

 $ ruby -v
 ruby 2.7.6p219 (2022-04-12 revision c9c2245c0a) [x86_64-darwin20]
 $ bundle rake clean compile
 ...
 $ DD_TRACE_DEBUG=true DD_PROFILING_ENABLED=true bundle exec ddtracerb exec ruby -e 'nil'
 D, [2022-05-06T12:17:41.554770 #19686] DEBUG -- ddtrace: [ddtrace]
 (/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/core/configuration/components.rb:340:in `startup!') Profiling started'

 # 2️⃣  Force library load failure:

 # (Delete the library version for the Ruby I'm using)
 $ rm lib/ddtrace_profiling_native_extension.2.7.6_x86_64-darwin20.bundle
 $ DD_TRACE_DEBUG=true DD_PROFILING_ENABLED=true bundle exec ddtracerb exec ruby -e 'nil'
 W, [2022-05-06T12:19:23.891711 #21159]  WARN -- ddtrace: [ddtrace]
 (/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/core/configuration/components.rb:345:in `startup!')
 Profiling was requested but is not supported, profiling disabled: There was an error loading the profiling native extension due to
 'Failure to load ddtrace_profiling_native_extension.2.7.6_x86_64-darwin20 due to
 dlopen(/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/profiling/../../ddtrace_profiling_native_extension.2.7.6_x86_64-darwin20.bundle, 5):
 image not found' at '/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/profiling/load_native_extension.rb:22:in `<top (required)>''

 # 3️⃣  Force a library incompatibility:

 # (Copy library compiled with a different Ruby version)
 $ cp lib/ddtrace_profiling_native_extension.3.2.0_x86_64-darwin20.bundle lib/ddtrace_profiling_native_extension.2.7.6_x86_64-darwin20.bundle
 $ DD_TRACE_DEBUG=true DD_PROFILING_ENABLED=true bundle exec ddtracerb exec ruby -e 'nil'
 W, [2022-05-06T12:22:24.036956 #21773]  WARN -- ddtrace: [ddtrace]
 (/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/core/configuration/components.rb:345:in `startup!')
 Profiling was requested but is not supported, profiling disabled: There was an error loading the profiling native extension due to
 Failure to load ddtrace_profiling_native_extension.2.7.6_x86_64-darwin20 due to library was compiled and linked to a different Ruby version'
 at '/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/profiling/load_native_extension.rb:22:in `<top (required)>'

 # 4️⃣  Force an initialization failure:

 # (Restore library clobbered in previous steps)
 $ bundle rake clean compile
 ...
 # (Rename expected initialization function)
 $ git diff -U0 lib/datadog/profiling/load_native_extension.rb
 diff --git a/lib/datadog/profiling/load_native_extension.rb b/lib/datadog/profiling/load_native_extension.rb
 index 5ea4bb32c..af964bade 100644
 --- a/lib/datadog/profiling/load_native_extension.rb
 +++ b/lib/datadog/profiling/load_native_extension.rb
 @@ -18 +18 @@ full_file_path = "#{__dir__}/../../#{extension_name}.#{RbConfig::CONFIG['DLEXT']
 -init_function_name = "Init_#{extension_name.split('.').first}"
 +init_function_name = "Init_#{extension_name.split('.').first}_kaboom
 $ DD_TRACE_DEBUG=true DD_PROFILING_ENABLED=true bundle exec ddtracerb exec ruby -e 'nil'
 W, [2022-05-06T12:27:55.706221 #23036]  WARN -- ddtrace: [ddtrace]
 (/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/core/configuration/components.rb:345:in `startup!')
 Profiling was requested but is not supported, profiling disabled: There was an error loading the profiling native extension due to
 'Failure to load ddtrace_profiling_native_extension.2.7.6_x86_64-darwin20 due to dlsym(0x7fe144151630,
   Init_ddtrace_profiling_native_extension_kaboom): symbol not found' at
 '/Users/ivo.anjo/datadog/dd-trace-rb/lib/datadog/profiling/load_native_extension.rb:22:in `<top (required)>''
```
ivoanjo added a commit to DataDog/dd-trace-rb that referenced this pull request Feb 6, 2025
**What does this PR do?**

This PR removes the `datadog_profiling_loader` native extension, as
it's no longer needed.

The profiling native loader was added in
#2003 .

Quoting from that PR's description:

> When Ruby loads a native extension (using `require`), it uses
> `dlopen(..., RTLD_LAZY | RTLD_GLOBAL)`
> (https://github.com/ruby/ruby/blob/67950a4c0a884bdb78d9beb4405ebf7459229b21/dln.c#L362).
>
> This means that every symbol exposed directly or indirectly by that
> native extension becomes visible to every other extension in the
> Ruby process. This can cause issues, see
> rubyjs/mini_racer#179 .
>
> Ruby's extension loading mechanism is not configurable -- there's
> no way to tell it to use different flags when calling `dlopen`.
> To get around this, this commit introduces introduces another
> extension (profiling loader) which has only a single responsibility:
> mimic Ruby's extension loading mechanism, but when calling
> `dlopen` use a different set of flags.
>
> This idea was shamelessly stolen from @lloeki's work in
> rubyjs/mini_racer#179, big thanks!

...and importantly ends with:

> Note that, that we know of, the profiling native extension only
> exposes one potentially problematic symbol:
> `rust_eh_personality` (coming from libddprof/libdatadog).
>
> Future versions of Rust have been patched not to expose this
> (see rust-lang/rust#95604 (comment))
> so we may want to revisit the need for this loader in the future,
> and perhaps delete it if we no longer require its services :)

And we have reached the situation predicted in that description:

1. Nowadays libdatadog no longer exposes `rust_eh_personality`

2. We have a test that validates that only expected symbols are
   exported by the libdatadog library
   (see DataDog/libdatadog#573 ).

   Any new symbols that show up would break shipping new
   libdatadog versions to rubygems.org until we review them.

3. The `libdatadog_api` extension, which we've been shipping for
   customers since release 2.3.0 back in July 2024 has always been
   loaded directly without a loader without issues.

Thus, I think it's the right time to get rid of the loader.

**Motivation:**

Having the loader around is not zero cost; we've run into/caused
a few issues ( #2250
and #3582 come to mind).

It also adds overhead to development: every time we need to rebuild
the extensions, it's an extra extension that needs to be prepared,
rebuilt, copied, etc.

I've been meaning to get rid of the loader for some time now,
and this came up again this week so I decided it was time to
do it.

**Additional Notes:**

In the future, we can always ressurrect this approach if we
figure out we need it again.

We've also discussed internally about proposing upstream
to the Ruby VM to maybe add an API to do what the loader was
doing, so that we wouldn't need the weird workaround.

We haven't yet decided if we're going to do that (help welcome!).

**How to test the change?**

The loader was responsible for loading the rest of profiling.

Thus, any test that uses profiling was also validating the loader
and now will validate that we're doing fine without it.

TL;DR green CI is good.
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants