datadog 2.40.0 → 2.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +85 -58
  3. data/ext/datadog_profiling_native_extension/collectors_stack.c +2 -2
  4. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -3
  5. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +26 -12
  6. data/ext/libdatadog_api/trace_exporter.c +409 -71
  7. data/ext/libdatadog_extconf_helpers.rb +1 -1
  8. data/lib/datadog/ai_guard/api_client.rb +1 -1
  9. data/lib/datadog/ai_guard/evaluation/request.rb +8 -8
  10. data/lib/datadog/ai_guard/evaluation.rb +10 -3
  11. data/lib/datadog/ai_guard/ext.rb +1 -1
  12. data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +21 -42
  13. data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +1 -1
  14. data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +1 -1
  15. data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +1 -1
  16. data/lib/datadog/appsec/configuration.rb +2 -2
  17. data/lib/datadog/appsec/context.rb +1 -1
  18. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +1 -1
  19. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +2 -2
  20. data/lib/datadog/appsec/contrib/devise/configuration.rb +1 -1
  21. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +2 -2
  22. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +2 -2
  23. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +1 -1
  24. data/lib/datadog/appsec/contrib/rack/ext.rb +2 -2
  25. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +2 -2
  26. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +2 -2
  27. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +2 -2
  28. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +2 -2
  29. data/lib/datadog/appsec/processor/rule_loader.rb +12 -12
  30. data/lib/datadog/appsec/response.rb +1 -1
  31. data/lib/datadog/appsec/route_normalizer/route_pattern.rb +3 -3
  32. data/lib/datadog/appsec/security_engine/engine.rb +3 -3
  33. data/lib/datadog/core/configuration/components.rb +2 -2
  34. data/lib/datadog/core/configuration/option_definition.rb +1 -1
  35. data/lib/datadog/core/configuration/options.rb +1 -1
  36. data/lib/datadog/core/diagnostics/environment_logger.rb +36 -1
  37. data/lib/datadog/core/metrics/helpers.rb +1 -1
  38. data/lib/datadog/core/metrics/options.rb +2 -2
  39. data/lib/datadog/core/process_discovery.rb +1 -1
  40. data/lib/datadog/core/remote/client.rb +1 -1
  41. data/lib/datadog/core/remote/configuration/repository.rb +2 -2
  42. data/lib/datadog/core/telemetry/configuration_value.rb +38 -0
  43. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +3 -1
  44. data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +1 -1
  45. data/lib/datadog/core/telemetry/event/app_started.rb +5 -24
  46. data/lib/datadog/core/telemetry/event/generate_metrics.rb +1 -1
  47. data/lib/datadog/core/telemetry/event/log.rb +2 -2
  48. data/lib/datadog/core/telemetry/metric.rb +2 -2
  49. data/lib/datadog/core/telemetry/request.rb +2 -2
  50. data/lib/datadog/core/transport/http.rb +1 -1
  51. data/lib/datadog/core/transport/transport.rb +1 -1
  52. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +127 -43
  53. data/lib/datadog/data_streams/processor.rb +14 -14
  54. data/lib/datadog/di/el/compiler.rb +23 -0
  55. data/lib/datadog/di/el/expression.rb +8 -5
  56. data/lib/datadog/di/instrumenter.rb +5 -4
  57. data/lib/datadog/di/probe_builder.rb +5 -4
  58. data/lib/datadog/di/probe_notification_builder.rb +2 -2
  59. data/lib/datadog/di/serializer.rb +29 -4
  60. data/lib/datadog/error_tracking/component.rb +1 -1
  61. data/lib/datadog/kit/appsec/events/v2.rb +2 -2
  62. data/lib/datadog/open_feature/exposures/batch_builder.rb +1 -1
  63. data/lib/datadog/open_feature/exposures/event.rb +5 -5
  64. data/lib/datadog/profiling/collectors/info.rb +1 -1
  65. data/lib/datadog/profiling/tasks/exec.rb +1 -1
  66. data/lib/datadog/symbol_database/extractor.rb +6 -6
  67. data/lib/datadog/tracing/configuration/dynamic/option.rb +4 -0
  68. data/lib/datadog/tracing/configuration/dynamic.rb +5 -3
  69. data/lib/datadog/tracing/contrib/action_cable/events.rb +1 -1
  70. data/lib/datadog/tracing/contrib/action_mailer/events.rb +1 -1
  71. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +2 -2
  72. data/lib/datadog/tracing/contrib/action_view/events.rb +1 -1
  73. data/lib/datadog/tracing/contrib/active_model_serializers/events.rb +1 -1
  74. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +1 -1
  75. data/lib/datadog/tracing/contrib/active_record/events.rb +1 -1
  76. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +2 -2
  77. data/lib/datadog/tracing/contrib/aws/ext.rb +1 -1
  78. data/lib/datadog/tracing/contrib/aws/services.rb +1 -1
  79. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +1 -1
  80. data/lib/datadog/tracing/contrib/ext.rb +3 -3
  81. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +1 -1
  82. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +1 -1
  83. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +1 -1
  84. data/lib/datadog/tracing/contrib/kafka/events.rb +1 -1
  85. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +1 -1
  86. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +1 -1
  87. data/lib/datadog/tracing/contrib/opensearch/ext.rb +1 -1
  88. data/lib/datadog/tracing/contrib/opensearch/quantize.rb +1 -1
  89. data/lib/datadog/tracing/contrib/patchable.rb +1 -1
  90. data/lib/datadog/tracing/contrib/patcher.rb +1 -1
  91. data/lib/datadog/tracing/contrib/que/tracer.rb +1 -1
  92. data/lib/datadog/tracing/contrib/racecar/events.rb +1 -1
  93. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +1 -1
  94. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +1 -1
  95. data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
  96. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +1 -1
  97. data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +1 -1
  98. data/lib/datadog/tracing/contrib/redis/quantize.rb +36 -2
  99. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +9 -3
  100. data/lib/datadog/tracing/contrib/sequel/utils.rb +1 -1
  101. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +1 -1
  102. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +1 -1
  103. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +1 -1
  104. data/lib/datadog/tracing/contrib/utils/quantization/hash_formatter.rb +1 -1
  105. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +1 -1
  106. data/lib/datadog/tracing/correlation.rb +2 -2
  107. data/lib/datadog/tracing/diagnostics/environment_logger.rb +2 -2
  108. data/lib/datadog/tracing/distributed/baggage.rb +1 -2
  109. data/lib/datadog/tracing/metadata/tagging.rb +1 -1
  110. data/lib/datadog/tracing/remote.rb +2 -2
  111. data/lib/datadog/tracing/span.rb +1 -1
  112. data/lib/datadog/tracing/span_operation.rb +1 -1
  113. data/lib/datadog/tracing/transport/io/traces.rb +1 -1
  114. data/lib/datadog/tracing/transport/native.rb +78 -54
  115. data/lib/datadog/tracing/writer.rb +1 -1
  116. data/lib/datadog/version.rb +1 -1
  117. metadata +6 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4894d3cc2404bab418412c2a96b2f15c2337f6e31dc567c6fd8d1ceafd372230
4
- data.tar.gz: e31bdb882385e48f731b925496b75964a02e17c4eb9c7b4a858083740009954c
3
+ metadata.gz: c9770ef0d02b2ecf56734c823b89ea642beb8512dae612904f0bc3d050852b44
4
+ data.tar.gz: b1e359c8eb8d26528b21c963c775b7cf8e5e227ca2cf7b88b322337d32c7283c
5
5
  SHA512:
6
- metadata.gz: 488fc94df9bda0fd8485f42934a08660a342617602e61a0fb999cb337239f98f226fc51e021df954ab74af985a6abfa38cc0b17069c00b0541c5100e8c961810
7
- data.tar.gz: '0197b5995f7861ddae8677caa96d419c89e2b25bb702d3c05e99e594562771c2c3193d8e9cc367bde5ebbd3fbd78362f55ea25fb1c071442b01d37a22c8d631e'
6
+ metadata.gz: 21335b21c2d0be965d3f3c972efab822767ddd6f28e3a1263497335300cf7a34b3fe1872d9037c1e40af909a897296e3946fac7ecd7b8e7b92c21c1ecdfc7a77
7
+ data.tar.gz: a2ee7baf6f4e6e45f6116629d09806db7d0bd171bb5aaa36f4cf65e2f7c53038be18e04b84b25f1a26bd87031ea223a8e6ced8f91cceb62f8a292bfd4fd76875
data/CHANGELOG.md CHANGED
@@ -2,53 +2,72 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [2.41.0] - 2026-08-13
6
+
7
+ ### Added
8
+
9
+ * Tracing: Integrations: Add support for `redis-rb` 6.0/RESP3. ([#6142][])
10
+ * Tracing: Native trace export now supports structured span metadata. ([#6130][])
11
+
12
+ ### Changed
13
+
14
+ * AppSec: Native trace export now encodes supported structured span metadata values without Ruby MessagePack encoding. ([#6132][])
15
+ * Tracing: Native trace export now writes structured span metadata directly through libdatadog. ([#6133][])
16
+
17
+ ### Fixed
18
+
19
+ * Profiling: Fix a rare crash (`SIGSEGV`) in the profiler that could occur when sampling a thread during `Thread.new`. ([#6173][])
20
+ * Profiling: Fix possible crash in `sample_thread()` when `rb_id2str()` returns `Qfalse`. ([#6138][])
21
+ * Tracing: Prevent runtime configuration telemetry from being rejected when header tags or sampling rules are updated remotely. ([#6126][])
22
+
5
23
  ## [2.40.0] - 2026-08-04
6
24
 
7
- ### Added
8
-
9
- * Profiling: Add experimental profiling setting to show class/module names in stack frames. Fix crash in `rb_iseq_path()` caused by incorrect GC marking. ([#6024][])
10
- * Tracing: Add an experimental native (`libdatadog`-backed) trace transport, selectable via `tracing.native_transport` ([#5971][])
11
-
12
- ### Changed
13
-
14
- * Core: Deprecate `time_now_provider` setting for removal; it no longer does anything. Please remove it from your `Datadog.configure block`. The datadog gem always uses the real non-mocked time, even when the timecop gem monkey-patches `Time` ([#6010][])
15
-
16
- ### Fixed
17
-
18
- * AppSec: Fix standalone billing issues for partially flushed traces ([#6116][])
19
- * Dynamic Instrumentation: Limit dynamic instrumentation regular expression evaluation time to 500ms ([#5908][])
20
- * Profiling: Fix missing native filename for static Ruby binaries ([#6097][])
25
+ ### Added
26
+
27
+ * Profiling: Add experimental profiling setting to show class/module names in stack frames ([#6024][])
28
+ * Tracing: Add an experimental native (`libdatadog`-backed) trace transport, selectable via `tracing.native_transport` ([#5971][])
29
+
30
+ ### Changed
31
+
32
+ * Core: Deprecate `time_now_provider` setting for removal; it no longer does anything. Please remove it from your `Datadog.configure block`. The datadog gem always uses the real non-mocked time, even when the timecop gem monkey-patches `Time` ([#6010][])
33
+
34
+ ### Fixed
35
+
36
+ * AppSec: Fix standalone billing issues for partially flushed traces ([#6116][])
37
+ * Dynamic Instrumentation: Limit dynamic instrumentation regular expression evaluation time to 500ms ([#5908][])
38
+ * Profiling: Fix missing native filename for static Ruby binaries ([#6097][])
39
+ * Profiling: Fix crash in `rb_iseq_path()` caused by incorrect GC marking ([#6024][])
21
40
  * Tracing: Fix missing or zero Kafka producer and connection span tags like `kafka.message_count` and `kafka.request_size` in the `ruby-kafka` integration. ([#6104][])
22
41
 
23
42
  ## [2.39.0] - 2026-07-22
24
43
 
25
- ### Added
26
-
27
- * Tracing: Integrations: Add database name and host to Sequel spans and infer `peer.service` so datastore dependencies appear in the service map. ([#6072][])
28
-
29
- ### Fixed
30
-
31
- * AppSec: Fix error in `devise` contrib for non-standard Warden session serialization. ([#6064][])
32
- * Dynamic Instrumentation: Fix dynamic instrumentation line probes failing to install when dynamic instrumentation is enabled remotely after application startup. ([#6050][])
33
- * Profiling: Fix crash when trying to sample during GC compaction ([#6056][])
44
+ ### Added
45
+
46
+ * Tracing: Integrations: Add database name and host to Sequel spans and infer `peer.service` so datastore dependencies appear in the service map. ([#6072][])
47
+
48
+ ### Fixed
49
+
50
+ * AppSec: Fix error in `devise` contrib for non-standard Warden session serialization. ([#6064][])
51
+ * Dynamic Instrumentation: Fix dynamic instrumentation line probes failing to install when dynamic instrumentation is enabled remotely after application startup. ([#6050][])
52
+ * Profiling: Fix crash when trying to sample during GC compaction ([#6056][])
34
53
  * Tracing: Integrations: Fix an `ArgumentError` (and the resulting `Kafka::BufferOverflow`) raised by the Kafka producer integration on Ruby 2.5 and 2.6. ([#6060][])
35
54
 
36
55
  ## [2.38.0] - 2026-07-16
37
56
 
38
- ### Added
39
-
40
- * Dynamic Instrumentation: Log probes now support capture expressions as an alternative to capturing the full local/argument scope ([#5845][])
41
- * SSI: Add support for Ruby 4.0 runtime ([#5981][])
42
- * SSI: Add support for Bundler 4.0 and RubyGems 4.0 ([#5981][])
43
-
44
- ### Fixed
45
-
46
- * AppSec: Fix Rack-based and Rails request body analysis when body parsing fails ([#5993][])
47
- * Profiling: Add workaround for crash when collecting frame information ([#6014][])
48
- * Profiling: Fix left-over state impacting samples when profiler gets stopped and started again ([#5960][])
49
- * Profiling: Fix Ruby 4.0.6 support by bumping minimum version of `datadog-ruby_core_source` to 3.5.3 ([#6047][])
50
- * Profiling: Disable live heap size profiling on Ruby 4.0 due to incompatibility ([#6022][])
51
- * Profiling: Disallow heap profiling on Ruby 4.1+ ([#6023][])
57
+ ### Added
58
+
59
+ * Dynamic Instrumentation: Log probes now support capture expressions as an alternative to capturing the full local/argument scope ([#5845][])
60
+ * SSI: Add support for Ruby 4.0 runtime ([#5981][])
61
+ * SSI: Add support for Bundler 4.0 and RubyGems 4.0 ([#5981][])
62
+
63
+ ### Fixed
64
+
65
+ * AppSec: Fix Rack-based and Rails request body analysis when body parsing fails ([#5993][])
66
+ * Profiling: Add workaround for crash when collecting frame information ([#6014][])
67
+ * Profiling: Fix left-over state impacting samples when profiler gets stopped and started again ([#5960][])
68
+ * Profiling: Fix Ruby 4.0.6 support by bumping minimum version of `datadog-ruby_core_source` to 3.5.3 ([#6047][])
69
+ * Profiling: Disable live heap size profiling on Ruby 4.0 due to incompatibility ([#6022][])
70
+ * Profiling: Disallow heap profiling on Ruby 4.1+ ([#6023][])
52
71
  * Tracing: Fix `pg` instrumentation which raised `ArgumentError` when calling `exec_params`, `exec_prepared` without a `params` argument, or their `async_`/`sync_` variants ([#6020][])
53
72
 
54
73
  ## [2.37.0] - 2026-07-06
@@ -80,26 +99,26 @@
80
99
 
81
100
  ## [2.36.0] - 2026-06-24
82
101
 
83
- ### Added
84
-
85
- * Tracing: Add `DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT` to control trace extraction behavior with `continue`, `restart`, and `ignore` modes ([#5844][])
86
- * AppSec: Add `DD_APPSEC_BODY_PARSING_SIZE_LIMIT` to control processing of request and response body size; set to 0 to disable ([#5877][])
87
- * AppSec: Detect attacks from inline fragments in GraphQL queries ([#5916][])
88
- * Dynamic Instrumentation: Show lazily loaded classes in UI ([#5697][])
89
-
90
- ### Changed
91
-
92
- * Dynamic Instrumentation: Reduce peak memory usage during Symbol Database extraction ([#5883][])
93
- * Profiling: Reduce profiler overhead by up to 50% by skipping redundant samples for threads without the GVL ([#5777][])
94
- * Profiling: Remove overhead when cleaning up dead threads ([#5816][])
95
-
96
- ### Fixed
97
-
98
- * Tracing: Workaround Ruby VM bug causing segmentation faults inside CachingResolver ([#5719][], [#5890][])
99
- * Dynamic Instrumentation: Prevent uploading stale class definitions for apps using `remove_const`-then-redefine patterns ([#5872][])
100
- * Profiling: Fix GC profiling being incorrectly disabled on Ruby 3.2.10 and 3.2.11 ([#5894][])
101
- * Profiling: Fix over-counting of the first allocation sample at profiler startup ([#5881][])
102
- * Profiling: Fix rare profiler crash during shutdown in heap profiling cleanup ([#5920][])
102
+ ### Added
103
+
104
+ * Tracing: Add `DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT` to control trace extraction behavior with `continue`, `restart`, and `ignore` modes ([#5844][])
105
+ * AppSec: Add `DD_APPSEC_BODY_PARSING_SIZE_LIMIT` to control processing of request and response body size; set to 0 to disable ([#5877][])
106
+ * AppSec: Detect attacks from inline fragments in GraphQL queries ([#5916][])
107
+ * Dynamic Instrumentation: Show lazily loaded classes in UI ([#5697][])
108
+
109
+ ### Changed
110
+
111
+ * Dynamic Instrumentation: Reduce peak memory usage during Symbol Database extraction ([#5883][])
112
+ * Profiling: Reduce profiler overhead by up to 50% by skipping redundant samples for threads without the GVL ([#5777][])
113
+ * Profiling: Remove overhead when cleaning up dead threads ([#5816][])
114
+
115
+ ### Fixed
116
+
117
+ * Tracing: Workaround Ruby VM bug causing segmentation faults inside CachingResolver ([#5719][], [#5890][])
118
+ * Dynamic Instrumentation: Prevent uploading stale class definitions for apps using `remove_const`-then-redefine patterns ([#5872][])
119
+ * Profiling: Fix GC profiling being incorrectly disabled on Ruby 3.2.10 and 3.2.11 ([#5894][])
120
+ * Profiling: Fix over-counting of the first allocation sample at profiler startup ([#5881][])
121
+ * Profiling: Fix rare profiler crash during shutdown in heap profiling cleanup ([#5920][])
103
122
  * Core: Fix exception message formatting from native extensions ([#5857][])
104
123
 
105
124
  ## [2.35.0] - 2026-06-03
@@ -3734,7 +3753,8 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
3734
3753
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3735
3754
 
3736
3755
 
3737
- [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.40.0...master
3756
+ [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.41.0...master
3757
+ [2.41.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.40.0...v2.41.0
3738
3758
  [2.40.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.39.0...v2.40.0
3739
3759
  [2.39.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.38.0...v2.39.0
3740
3760
  [2.38.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.37.0...v2.38.0
@@ -5549,6 +5569,13 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
5549
5569
  [#6097]: https://github.com/DataDog/dd-trace-rb/issues/6097
5550
5570
  [#6104]: https://github.com/DataDog/dd-trace-rb/issues/6104
5551
5571
  [#6116]: https://github.com/DataDog/dd-trace-rb/issues/6116
5572
+ [#6126]: https://github.com/DataDog/dd-trace-rb/issues/6126
5573
+ [#6130]: https://github.com/DataDog/dd-trace-rb/issues/6130
5574
+ [#6132]: https://github.com/DataDog/dd-trace-rb/issues/6132
5575
+ [#6133]: https://github.com/DataDog/dd-trace-rb/issues/6133
5576
+ [#6138]: https://github.com/DataDog/dd-trace-rb/issues/6138
5577
+ [#6142]: https://github.com/DataDog/dd-trace-rb/issues/6142
5578
+ [#6173]: https://github.com/DataDog/dd-trace-rb/issues/6173
5552
5579
  [@AdrianLC]: https://github.com/AdrianLC
5553
5580
  [@Azure7111]: https://github.com/Azure7111
5554
5581
  [@BabyGroot]: https://github.com/BabyGroot
@@ -326,7 +326,7 @@ void sample_thread(
326
326
  iseq = frame.as.ruby_frame.iseq;
327
327
 
328
328
  VALUE filename = ddtrace_iseq_path(iseq);
329
- filename_slice = NIL_P(filename) ? DDOG_CHARSLICE_C("") : char_slice_from_ruby_string(filename);
329
+ filename_slice = char_slice_from_ruby_string(filename);
330
330
  line = frame.as.ruby_frame.line;
331
331
 
332
332
  last_ruby_frame_filename = filename_slice;
@@ -350,7 +350,7 @@ void sample_thread(
350
350
  // TODO: name_slice is currently the unqualified method name
351
351
  // because we don't always use qualified method names yet, so we don't always compute it,
352
352
  // and checks below need to compare to something stable until we always qualified method names.
353
- ddog_CharSlice name_slice = char_slice_from_ruby_string(name);
353
+ ddog_CharSlice name_slice = (name == Qfalse) ? DDOG_CHARSLICE_C("") : char_slice_from_ruby_string(name);
354
354
 
355
355
  ddog_CharSlice qualified_name = DDOG_CHARSLICE_C("");
356
356
  if (show_classes) {
@@ -80,15 +80,15 @@ module Datadog
80
80
  "For help solving this issue, please contact Datadog support at",
81
81
  "<https://docs.datadoghq.com/help/>.",
82
82
  "You can also check out the Continuous Profiler troubleshooting page at",
83
- "<https://dtdg.co/ruby-profiler-troubleshooting>."
83
+ "<https://dtdg.co/ruby-profiler-troubleshooting>.",
84
84
  ].freeze
85
85
 
86
86
  GET_IN_TOUCH = [
87
- "Get in touch with us if you're interested in profiling your app!"
87
+ "Get in touch with us if you're interested in profiling your app!",
88
88
  ].freeze
89
89
 
90
90
  UPGRADE_RUBY = [
91
- "Upgrade to a modern Ruby to enable profiling for your app."
91
+ "Upgrade to a modern Ruby to enable profiling for your app.",
92
92
  ].freeze
93
93
 
94
94
  # Validation for this check is done in extconf.rb because it relies on mkmf
@@ -59,6 +59,7 @@
59
59
  #include "private_vm_api_access.h"
60
60
 
61
61
  static inline const rb_callable_method_entry_t* get_cfunc_method_entry(const rb_control_frame_t *cfp);
62
+ static const rb_callable_method_entry_t* safe_vm_frame_method_entry(const rb_control_frame_t *cfp);
62
63
 
63
64
  // MRI has a similar rb_thread_ptr() function which we can't call it directly
64
65
  // because Ruby does not expose the thread_data_type publicly.
@@ -525,7 +526,7 @@ int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, frame_info *st
525
526
  continue;
526
527
  }
527
528
 
528
- cme = rb_vm_frame_method_entry(cfp);
529
+ cme = safe_vm_frame_method_entry(cfp);
529
530
 
530
531
  // Upstream (Ruby 4.0) does:
531
532
  // if (cme && cme->def->type == VM_METHOD_TYPE_ISEQ) {
@@ -639,31 +640,36 @@ check_method_entry(VALUE obj, int can_be_svar) {
639
640
 
640
641
  return NULL;
641
642
  }
643
+ #endif // RUBY_MJIT_HEADER
642
644
 
643
- // Taken from upstream vm_insnhelper.c at commit 5f10bd634fb6ae8f74a4ea730176233b0ca96954 (March 2022, Ruby 3.2 trunk)
644
- // Copyright (C) 2007 Koichi Sasada
645
- // to support our custom rb_profile_frames (see above)
646
- //
647
- // While older Rubies may have this function, the symbol is not exported which leads to dynamic loader issues, e.g.
648
- // `dyld: lazy symbol binding failed: Symbol not found: _rb_vm_frame_method_entry`.
645
+ // Identical to upstream rb_vm_frame_method_entry (vm_insnhelper.c) with two additions:
646
+ // 1. FIXNUM_P check on ep[FLAGS] before each iteration to detect torn EPs
647
+ // 2. NULL check on ep after VM_ENV_PREV_EP
649
648
  //
650
- // Modifications: None
651
- MJIT_STATIC const rb_callable_method_entry_t *
652
- rb_vm_frame_method_entry(const rb_control_frame_t *cfp)
649
+ // When the profiler's signal handler interrupts vm_make_env_each (vm.c) mid-escape,
650
+ // a child frame's SPECVAL can still point to the parent's old stack EP whose flags
651
+ // slot has been overwritten with (VALUE)env for GC marking.
652
+ static const rb_callable_method_entry_t *
653
+ safe_vm_frame_method_entry(const rb_control_frame_t *cfp)
653
654
  {
654
655
  const VALUE *ep = cfp->ep;
655
656
  rb_callable_method_entry_t *me;
656
657
 
657
- while (!VM_ENV_LOCAL_P(ep)) {
658
+ // Torn-EP check before VM_ENV_LOCAL_P, check_method_entry, and VM_ENV_PREV_EP
659
+ // dereference ep
660
+ while (FIXNUM_P(ep[VM_ENV_DATA_INDEX_FLAGS]) && !VM_ENV_LOCAL_P(ep)) {
658
661
  if ((me = check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], FALSE)) != NULL) {
659
662
  return me;
660
663
  }
661
664
  ep = VM_ENV_PREV_EP(ep);
665
+ if (ep == NULL) return NULL;
662
666
  }
663
667
 
668
+ // If we exited because of a torn EP (failed FIXNUM_P), bail out
669
+ if (!FIXNUM_P(ep[VM_ENV_DATA_INDEX_FLAGS])) return NULL;
670
+
664
671
  return check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
665
672
  }
666
- #endif // RUBY_MJIT_HEADER
667
673
 
668
674
  // Optimized version of rb_vm_frame_method_entry() for cfunc frames.
669
675
  // Cfunc frames always have VM_ENV_FLAG_LOCAL set, so ep[-2] is the cme directly
@@ -943,6 +949,7 @@ static bool has_permanent_classpath(DDTRACE_UNUSED VALUE mod, DDTRACE_UNUSED VAL
943
949
 
944
950
  #define ONLY_METHOD_NAME ((ssize_t) -1)
945
951
  #define BUFFER_OUT_OF_SPACE ((ssize_t) -2)
952
+ #define NO_METHOD_NAME ((ssize_t) -3)
946
953
 
947
954
  static ssize_t rb_gen_method_name(VALUE owner, VALUE method_name, char *buf, size_t buf_size) {
948
955
  if (!(RB_TYPE_P(owner, T_CLASS) || RB_TYPE_P(owner, T_MODULE))) {
@@ -1032,6 +1039,9 @@ static ssize_t calculate_iseq_label(VALUE owner, const rb_iseq_t *iseq, char *bu
1032
1039
  ssize_t ddtrace_location_label(const rb_callable_method_entry_t *cme, const rb_iseq_t *iseq, char *buf, size_t buf_size) {
1033
1040
  if (location_cfunc_p(cme)) {
1034
1041
  VALUE method_name = rb_id2str(cme->def->original_id);
1042
+ if (method_name == Qfalse) {
1043
+ return NO_METHOD_NAME;
1044
+ }
1035
1045
  return rb_gen_method_name(cme->owner, method_name, buf, buf_size);
1036
1046
  } else {
1037
1047
  VALUE owner = cme ? cme->owner : Qnil;
@@ -1039,6 +1049,7 @@ ssize_t ddtrace_location_label(const rb_callable_method_entry_t *cme, const rb_i
1039
1049
  }
1040
1050
  }
1041
1051
 
1052
+ // Returns a String or Qfalse (like rb_id2str())
1042
1053
  VALUE ddtrace_location_base_label(const rb_callable_method_entry_t *cme, const rb_iseq_t *iseq) {
1043
1054
  if (location_cfunc_p(cme)) {
1044
1055
  return rb_id2str(cme->def->original_id);
@@ -1047,10 +1058,13 @@ VALUE ddtrace_location_base_label(const rb_callable_method_entry_t *cme, const r
1047
1058
  }
1048
1059
  }
1049
1060
 
1061
+ // Always returns a String
1050
1062
  VALUE ddtrace_iseq_base_label(const rb_iseq_t *iseq) {
1051
1063
  return rb_iseq_base_label(iseq);
1052
1064
  }
1053
1065
 
1066
+ // Always returns a String
1067
+ // See https://github.com/ruby/ruby/blob/75aeb225b8558ff908ea78bf608dfbba09bdc2f9/iseq.c#L564-L565
1054
1068
  VALUE ddtrace_iseq_path(const rb_iseq_t *iseq) {
1055
1069
  return rb_iseq_path(iseq);
1056
1070
  }