datadog 2.8.0 → 2.9.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 (108) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -1
  3. data/ext/datadog_profiling_native_extension/clock_id.h +2 -2
  4. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +64 -54
  5. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
  6. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
  7. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +16 -16
  8. data/ext/datadog_profiling_native_extension/collectors_stack.c +7 -7
  9. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +219 -122
  10. data/ext/datadog_profiling_native_extension/heap_recorder.h +1 -1
  11. data/ext/datadog_profiling_native_extension/http_transport.c +4 -4
  12. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +3 -0
  13. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -1
  14. data/ext/datadog_profiling_native_extension/profiling.c +10 -8
  15. data/ext/datadog_profiling_native_extension/ruby_helpers.c +8 -8
  16. data/ext/datadog_profiling_native_extension/stack_recorder.c +54 -54
  17. data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -1
  18. data/ext/datadog_profiling_native_extension/time_helpers.h +1 -1
  19. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
  20. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
  21. data/ext/libdatadog_api/crashtracker.c +3 -0
  22. data/lib/datadog/appsec/assets/waf_rules/recommended.json +355 -157
  23. data/lib/datadog/appsec/assets/waf_rules/strict.json +62 -32
  24. data/lib/datadog/appsec/context.rb +54 -0
  25. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +7 -7
  26. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +6 -6
  27. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +4 -4
  28. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +19 -28
  29. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +5 -5
  30. data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
  31. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +64 -96
  32. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +10 -10
  33. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +5 -5
  34. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +6 -6
  35. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
  36. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +43 -49
  37. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +21 -32
  38. data/lib/datadog/appsec/contrib/rails/patcher.rb +1 -1
  39. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +6 -6
  40. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +41 -63
  41. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +2 -2
  42. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +5 -5
  43. data/lib/datadog/appsec/event.rb +6 -6
  44. data/lib/datadog/appsec/ext.rb +3 -1
  45. data/lib/datadog/appsec/monitor/gateway/watcher.rb +22 -32
  46. data/lib/datadog/appsec/monitor/reactive/set_user.rb +5 -5
  47. data/lib/datadog/appsec/processor/rule_loader.rb +0 -3
  48. data/lib/datadog/appsec.rb +3 -3
  49. data/lib/datadog/auto_instrument.rb +3 -0
  50. data/lib/datadog/core/configuration/agent_settings_resolver.rb +39 -11
  51. data/lib/datadog/core/configuration/components.rb +4 -2
  52. data/lib/datadog/core/configuration.rb +1 -1
  53. data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
  54. data/lib/datadog/core/crashtracking/component.rb +1 -3
  55. data/lib/datadog/core/telemetry/event.rb +87 -3
  56. data/lib/datadog/core/telemetry/logging.rb +2 -2
  57. data/lib/datadog/core/telemetry/metric.rb +22 -0
  58. data/lib/datadog/core/telemetry/worker.rb +33 -0
  59. data/lib/datadog/di/base.rb +115 -0
  60. data/lib/datadog/di/code_tracker.rb +7 -4
  61. data/lib/datadog/di/component.rb +17 -11
  62. data/lib/datadog/di/configuration/settings.rb +11 -1
  63. data/lib/datadog/di/contrib/railtie.rb +15 -0
  64. data/lib/datadog/di/contrib.rb +26 -0
  65. data/lib/datadog/di/error.rb +5 -0
  66. data/lib/datadog/di/instrumenter.rb +39 -18
  67. data/lib/datadog/di/{init.rb → preload.rb} +2 -4
  68. data/lib/datadog/di/probe_manager.rb +4 -4
  69. data/lib/datadog/di/probe_notification_builder.rb +16 -2
  70. data/lib/datadog/di/probe_notifier_worker.rb +5 -6
  71. data/lib/datadog/di/remote.rb +4 -4
  72. data/lib/datadog/di/transport.rb +2 -4
  73. data/lib/datadog/di.rb +5 -108
  74. data/lib/datadog/kit/appsec/events.rb +3 -3
  75. data/lib/datadog/kit/identity.rb +4 -4
  76. data/lib/datadog/profiling/component.rb +55 -53
  77. data/lib/datadog/profiling/http_transport.rb +1 -26
  78. data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
  79. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
  80. data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
  81. data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
  82. data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
  83. data/lib/datadog/tracing/contrib/active_record/integration.rb +6 -2
  84. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +3 -1
  85. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +3 -1
  86. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
  87. data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
  88. data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
  89. data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
  90. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
  91. data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
  92. data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -0
  93. data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
  94. data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
  95. data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
  96. data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
  97. data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
  98. data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
  99. data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
  100. data/lib/datadog/tracing/span.rb +12 -4
  101. data/lib/datadog/tracing/span_event.rb +123 -3
  102. data/lib/datadog/tracing/span_operation.rb +6 -0
  103. data/lib/datadog/tracing/transport/serializable_trace.rb +24 -6
  104. data/lib/datadog/version.rb +1 -1
  105. metadata +19 -10
  106. data/lib/datadog/appsec/reactive/operation.rb +0 -68
  107. data/lib/datadog/appsec/scope.rb +0 -58
  108. data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f4b811f0c5014e6f325ac55406d225454a2101cc7576df15657ebc74cf47542
4
- data.tar.gz: 20c6095b149238c31501bd0be8eb4363a9b22011f750d5f2d68e3f8b730bb970
3
+ metadata.gz: 5666f79db7cd7abdb43c961e51978ef2711ec4566ba8090ebafeb074d06dec33
4
+ data.tar.gz: 907d0787aedf67f9db8ff57a2f16b6216cbc5514bb2a47005026f0e5263e7168
5
5
  SHA512:
6
- metadata.gz: af600463b83509c10417cc90fa808b4148baaa0961bde7aa2d1cdea98c6537a68fdde456af2d700a1e8d795a49fbc9aef3f61d68cc81949132abd8d9165ed19e
7
- data.tar.gz: 28977b792b9f957e57bf8386b759a59257d0a74c161038ae7f2f4a1b0f8016b8c3828cf71092920c6fd14fd6640e5ab4dbf987dec257fc2ff54061f7342c20bf
6
+ metadata.gz: 22a55675bb273845ec829245812e9f447767878d924083d505ddc8ec6dc97c28770252b3bbb25f0811ab4bf92e44bf2e7439815b61bc14c8d98a8025c7f1db13
7
+ data.tar.gz: 6a71cfdfbb3bd78949c23e11cbfcc9cea6a582925812862e0ff9a8c8f6ecded1807ee0d52e36c4422cb49181e0138e5e5d566a9895ccf46c0a0cd91fc74cfd64
data/CHANGELOG.md CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [2.9.0] - 2025-01-15
6
+
7
+ ### Added
8
+
9
+ * Core: add support for Ruby 3.4 ([#4249][])
10
+ * Integrations: add a new option for `ActiveSupport` to disable adding the `cache_key` as a Span Tag with the `cache_key_enabled` option ([#4022][])
11
+
12
+ ### Changed
13
+
14
+ * Dynamic instrumentation: move DI preloading to `datadog/di/preload` ([#4288][])
15
+ * Dynamic instrumentation: dd-trace-rb now reports whether dynamic instrumentation is enabled in startup summary report ([#4285][])
16
+ * Dynamic instrumentation: improve loading of DI components ([#4272][], [#4239][])
17
+ * Dynamic instrumentation: logging of internal conditions is now done on debug level ([#4266][])
18
+ * Dynamic instrumentation: report instrumentation error for line probes when the target file is loaded but not in code tracker registry ([#4208][])
19
+ * Profiling: require datadog-ruby_core_source >= 3.3.7 to ensure Ruby 3.4 support ([#4228][])
20
+
21
+ ### Fixed
22
+
23
+ * Core: fix a crash in crashtracker when agent hostname is an IPv6 address ([#4237][])
24
+ * Profiling: fix allocation profiling + otel tracing causing Ruby crash ([#4240][])
25
+ * Profiling: fix profiling warnings being really hard to silence ([#4232][])
26
+
5
27
  ## [2.8.0] - 2024-12-10
6
28
 
7
29
  ### Added
@@ -3057,7 +3079,8 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
3057
3079
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3058
3080
 
3059
3081
 
3060
- [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.8.0...master
3082
+ [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.9.0...master
3083
+ [2.9.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.8.0...v2.9.0
3061
3084
  [2.8.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.7.1...v2.8.0
3062
3085
  [2.7.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.6.0...v2.7.0
3063
3086
  [2.6.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.5.0...v2.6.0
@@ -4499,6 +4522,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4499
4522
  [#3997]: https://github.com/DataDog/dd-trace-rb/issues/3997
4500
4523
  [#4014]: https://github.com/DataDog/dd-trace-rb/issues/4014
4501
4524
  [#4020]: https://github.com/DataDog/dd-trace-rb/issues/4020
4525
+ [#4022]: https://github.com/DataDog/dd-trace-rb/issues/4022
4502
4526
  [#4024]: https://github.com/DataDog/dd-trace-rb/issues/4024
4503
4527
  [#4027]: https://github.com/DataDog/dd-trace-rb/issues/4027
4504
4528
  [#4033]: https://github.com/DataDog/dd-trace-rb/issues/4033
@@ -4519,6 +4543,17 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4519
4543
  [#4195]: https://github.com/DataDog/dd-trace-rb/issues/4195
4520
4544
  [#4196]: https://github.com/DataDog/dd-trace-rb/issues/4196
4521
4545
  [#4197]: https://github.com/DataDog/dd-trace-rb/issues/4197
4546
+ [#4208]: https://github.com/DataDog/dd-trace-rb/issues/4208
4547
+ [#4228]: https://github.com/DataDog/dd-trace-rb/issues/4228
4548
+ [#4232]: https://github.com/DataDog/dd-trace-rb/issues/4232
4549
+ [#4237]: https://github.com/DataDog/dd-trace-rb/issues/4237
4550
+ [#4239]: https://github.com/DataDog/dd-trace-rb/issues/4239
4551
+ [#4240]: https://github.com/DataDog/dd-trace-rb/issues/4240
4552
+ [#4249]: https://github.com/DataDog/dd-trace-rb/issues/4249
4553
+ [#4266]: https://github.com/DataDog/dd-trace-rb/issues/4266
4554
+ [#4272]: https://github.com/DataDog/dd-trace-rb/issues/4272
4555
+ [#4285]: https://github.com/DataDog/dd-trace-rb/issues/4285
4556
+ [#4288]: https://github.com/DataDog/dd-trace-rb/issues/4288
4522
4557
  [@AdrianLC]: https://github.com/AdrianLC
4523
4558
  [@Azure7111]: https://github.com/Azure7111
4524
4559
  [@BabyGroot]: https://github.com/BabyGroot
@@ -5,13 +5,13 @@
5
5
  #include <ruby.h>
6
6
 
7
7
  // Contains the operating-system specific identifier needed to fetch CPU-time, and a flag to indicate if we failed to fetch it
8
- typedef struct thread_cpu_time_id {
8
+ typedef struct {
9
9
  bool valid;
10
10
  clockid_t clock_id;
11
11
  } thread_cpu_time_id;
12
12
 
13
13
  // Contains the current cpu time, and a flag to indicate if we failed to fetch it
14
- typedef struct thread_cpu_time {
14
+ typedef struct {
15
15
  bool valid;
16
16
  long result_ns;
17
17
  } thread_cpu_time;
@@ -92,7 +92,7 @@ unsigned int MAX_ALLOC_WEIGHT = 10000;
92
92
  #endif
93
93
 
94
94
  // Contains state for a single CpuAndWallTimeWorker instance
95
- struct cpu_and_wall_time_worker_state {
95
+ typedef struct {
96
96
  // These are immutable after initialization
97
97
 
98
98
  bool gc_profiling_enabled;
@@ -187,7 +187,7 @@ struct cpu_and_wall_time_worker_state {
187
187
  uint64_t gvl_sampling_time_ns_max;
188
188
  uint64_t gvl_sampling_time_ns_total;
189
189
  } stats;
190
- };
190
+ } cpu_and_wall_time_worker_state;
191
191
 
192
192
  static VALUE _native_new(VALUE klass);
193
193
  static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
@@ -195,7 +195,7 @@ static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr);
195
195
  static VALUE _native_sampling_loop(VALUE self, VALUE instance);
196
196
  static VALUE _native_stop(DDTRACE_UNUSED VALUE _self, VALUE self_instance, VALUE worker_thread);
197
197
  static VALUE stop(VALUE self_instance, VALUE optional_exception);
198
- static void stop_state(struct cpu_and_wall_time_worker_state *state, VALUE optional_exception);
198
+ static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exception);
199
199
  static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info, DDTRACE_UNUSED void *_ucontext);
200
200
  static void *run_sampling_trigger_loop(void *state_ptr);
201
201
  static void interrupt_sampling_trigger_loop(void *state_ptr);
@@ -221,14 +221,14 @@ static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance);
221
221
  static VALUE _native_stats_reset_not_thread_safe(DDTRACE_UNUSED VALUE self, VALUE instance);
222
222
  void *simulate_sampling_signal_delivery(DDTRACE_UNUSED void *_unused);
223
223
  static void grab_gvl_and_sample(void);
224
- static void reset_stats_not_thread_safe(struct cpu_and_wall_time_worker_state *state);
224
+ static void reset_stats_not_thread_safe(cpu_and_wall_time_worker_state *state);
225
225
  static void sleep_for(uint64_t time_ns);
226
226
  static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self);
227
227
  static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *unused2);
228
- static void disable_tracepoints(struct cpu_and_wall_time_worker_state *state);
228
+ static void disable_tracepoints(cpu_and_wall_time_worker_state *state);
229
229
  static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self);
230
230
  static VALUE rescued_sample_allocation(VALUE tracepoint_data);
231
- static void delayed_error(struct cpu_and_wall_time_worker_state *state, const char *error);
231
+ static void delayed_error(cpu_and_wall_time_worker_state *state, const char *error);
232
232
  static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg);
233
233
  static VALUE _native_hold_signals(DDTRACE_UNUSED VALUE self);
234
234
  static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self);
@@ -262,7 +262,7 @@ static VALUE _native_gvl_profiling_hook_active(DDTRACE_UNUSED VALUE self, VALUE
262
262
  // This global state is needed because a bunch of functions on this file need to access it from situations
263
263
  // (e.g. signal handler) where it's impossible or just awkward to pass it as an argument.
264
264
  static VALUE active_sampler_instance = Qnil;
265
- static struct cpu_and_wall_time_worker_state *active_sampler_instance_state = NULL;
265
+ static cpu_and_wall_time_worker_state *active_sampler_instance_state = NULL;
266
266
 
267
267
  // See handle_sampling_signal for details on what this does
268
268
  #ifdef NO_POSTPONED_TRIGGER
@@ -334,7 +334,7 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
334
334
  rb_define_singleton_method(testing_module, "_native_gvl_profiling_hook_active", _native_gvl_profiling_hook_active, 1);
335
335
  }
336
336
 
337
- // This structure is used to define a Ruby object that stores a pointer to a struct cpu_and_wall_time_worker_state
337
+ // This structure is used to define a Ruby object that stores a pointer to a cpu_and_wall_time_worker_state
338
338
  // See also https://github.com/ruby/ruby/blob/master/doc/extension.rdoc for how this works
339
339
  static const rb_data_type_t cpu_and_wall_time_worker_typed_data = {
340
340
  .wrap_struct_name = "Datadog::Profiling::Collectors::CpuAndWallTimeWorker",
@@ -350,7 +350,7 @@ static const rb_data_type_t cpu_and_wall_time_worker_typed_data = {
350
350
  static VALUE _native_new(VALUE klass) {
351
351
  long now = monotonic_wall_time_now_ns(RAISE_ON_FAILURE);
352
352
 
353
- struct cpu_and_wall_time_worker_state *state = ruby_xcalloc(1, sizeof(struct cpu_and_wall_time_worker_state));
353
+ cpu_and_wall_time_worker_state *state = ruby_xcalloc(1, sizeof(cpu_and_wall_time_worker_state));
354
354
 
355
355
  // Note: Any exceptions raised from this note until the TypedData_Wrap_Struct call will lead to the state memory
356
356
  // being leaked.
@@ -414,8 +414,8 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
414
414
  ENFORCE_BOOLEAN(gvl_profiling_enabled);
415
415
  ENFORCE_BOOLEAN(skip_idle_samples_for_testing)
416
416
 
417
- struct cpu_and_wall_time_worker_state *state;
418
- TypedData_Get_Struct(self_instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
417
+ cpu_and_wall_time_worker_state *state;
418
+ TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
419
419
 
420
420
  state->gc_profiling_enabled = (gc_profiling_enabled == Qtrue);
421
421
  state->no_signals_workaround_enabled = (no_signals_workaround_enabled == Qtrue);
@@ -445,7 +445,7 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
445
445
 
446
446
  // Since our state contains references to Ruby objects, we need to tell the Ruby GC about them
447
447
  static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr) {
448
- struct cpu_and_wall_time_worker_state *state = (struct cpu_and_wall_time_worker_state *) state_ptr;
448
+ cpu_and_wall_time_worker_state *state = (cpu_and_wall_time_worker_state *) state_ptr;
449
449
 
450
450
  rb_gc_mark(state->thread_context_collector_instance);
451
451
  rb_gc_mark(state->idle_sampling_helper_instance);
@@ -457,8 +457,8 @@ static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr) {
457
457
 
458
458
  // Called in a background thread created in CpuAndWallTimeWorker#start
459
459
  static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
460
- struct cpu_and_wall_time_worker_state *state;
461
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
460
+ cpu_and_wall_time_worker_state *state;
461
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
462
462
 
463
463
  // If we already got a delayed exception registered even before starting, raise before starting
464
464
  if (state->failure_exception != Qnil) {
@@ -466,7 +466,7 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
466
466
  rb_exc_raise(state->failure_exception);
467
467
  }
468
468
 
469
- struct cpu_and_wall_time_worker_state *old_state = active_sampler_instance_state;
469
+ cpu_and_wall_time_worker_state *old_state = active_sampler_instance_state;
470
470
  if (old_state != NULL) {
471
471
  if (is_thread_alive(old_state->owner_thread)) {
472
472
  rb_raise(
@@ -546,15 +546,15 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
546
546
  }
547
547
 
548
548
  static VALUE _native_stop(DDTRACE_UNUSED VALUE _self, VALUE self_instance, VALUE worker_thread) {
549
- struct cpu_and_wall_time_worker_state *state;
550
- TypedData_Get_Struct(self_instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
549
+ cpu_and_wall_time_worker_state *state;
550
+ TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
551
551
 
552
552
  state->stop_thread = worker_thread;
553
553
 
554
554
  return stop(self_instance, /* optional_exception: */ Qnil);
555
555
  }
556
556
 
557
- static void stop_state(struct cpu_and_wall_time_worker_state *state, VALUE optional_exception) {
557
+ static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exception) {
558
558
  atomic_store(&state->should_run, false);
559
559
  state->failure_exception = optional_exception;
560
560
 
@@ -563,8 +563,8 @@ static void stop_state(struct cpu_and_wall_time_worker_state *state, VALUE optio
563
563
  }
564
564
 
565
565
  static VALUE stop(VALUE self_instance, VALUE optional_exception) {
566
- struct cpu_and_wall_time_worker_state *state;
567
- TypedData_Get_Struct(self_instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
566
+ cpu_and_wall_time_worker_state *state;
567
+ TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
568
568
 
569
569
  stop_state(state, optional_exception);
570
570
 
@@ -575,7 +575,7 @@ static VALUE stop(VALUE self_instance, VALUE optional_exception) {
575
575
  // We need to be careful not to change any state that may be observed OR to restore it if we do. For instance, if anything
576
576
  // we do here can set `errno`, then we must be careful to restore the old `errno` after the fact.
577
577
  static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info, DDTRACE_UNUSED void *_ucontext) {
578
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
578
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
579
579
 
580
580
  // This can potentially happen if the CpuAndWallTimeWorker was stopped while the signal delivery was happening; nothing to do
581
581
  if (state == NULL) return;
@@ -650,7 +650,7 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
650
650
 
651
651
  // The actual sampling trigger loop always runs **without** the global vm lock.
652
652
  static void *run_sampling_trigger_loop(void *state_ptr) {
653
- struct cpu_and_wall_time_worker_state *state = (struct cpu_and_wall_time_worker_state *) state_ptr;
653
+ cpu_and_wall_time_worker_state *state = (cpu_and_wall_time_worker_state *) state_ptr;
654
654
 
655
655
  uint64_t minimum_time_between_signals = MILLIS_AS_NS(10);
656
656
 
@@ -709,13 +709,13 @@ static void *run_sampling_trigger_loop(void *state_ptr) {
709
709
 
710
710
  // This is called by the Ruby VM when it wants to shut down the background thread
711
711
  static void interrupt_sampling_trigger_loop(void *state_ptr) {
712
- struct cpu_and_wall_time_worker_state *state = (struct cpu_and_wall_time_worker_state *) state_ptr;
712
+ cpu_and_wall_time_worker_state *state = (cpu_and_wall_time_worker_state *) state_ptr;
713
713
 
714
714
  atomic_store(&state->should_run, false);
715
715
  }
716
716
 
717
717
  static void sample_from_postponed_job(DDTRACE_UNUSED void *_unused) {
718
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
718
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
719
719
 
720
720
  // This can potentially happen if the CpuAndWallTimeWorker was stopped while the postponed job was waiting to be executed; nothing to do
721
721
  if (state == NULL) return;
@@ -735,8 +735,8 @@ static void sample_from_postponed_job(DDTRACE_UNUSED void *_unused) {
735
735
  }
736
736
 
737
737
  static VALUE rescued_sample_from_postponed_job(VALUE self_instance) {
738
- struct cpu_and_wall_time_worker_state *state;
739
- TypedData_Get_Struct(self_instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
738
+ cpu_and_wall_time_worker_state *state;
739
+ TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
740
740
 
741
741
  long wall_time_ns_before_sample = monotonic_wall_time_now_ns(RAISE_ON_FAILURE);
742
742
 
@@ -791,8 +791,8 @@ static VALUE _native_current_sigprof_signal_handler(DDTRACE_UNUSED VALUE self) {
791
791
  }
792
792
 
793
793
  static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance) {
794
- struct cpu_and_wall_time_worker_state *state;
795
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
794
+ cpu_and_wall_time_worker_state *state;
795
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
796
796
 
797
797
  // Final preparations: Setup signal handler and enable tracepoints. We run these here and not in `_native_sampling_loop`
798
798
  // because they may raise exceptions.
@@ -842,7 +842,7 @@ static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance) {
842
842
  // This method exists only to enable testing Datadog::Profiling::Collectors::CpuAndWallTimeWorker behavior using RSpec.
843
843
  // It SHOULD NOT be used for other purposes.
844
844
  static VALUE _native_is_running(DDTRACE_UNUSED VALUE self, VALUE instance) {
845
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
845
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
846
846
 
847
847
  return (state != NULL && is_thread_alive(state->owner_thread) && state->self_instance == instance) ? Qtrue : Qfalse;
848
848
  }
@@ -875,8 +875,8 @@ static VALUE _native_trigger_sample(DDTRACE_UNUSED VALUE self) {
875
875
  // This method exists only to enable testing Datadog::Profiling::Collectors::CpuAndWallTimeWorker behavior using RSpec.
876
876
  // It SHOULD NOT be used for other purposes.
877
877
  static VALUE _native_gc_tracepoint(DDTRACE_UNUSED VALUE self, VALUE instance) {
878
- struct cpu_and_wall_time_worker_state *state;
879
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
878
+ cpu_and_wall_time_worker_state *state;
879
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
880
880
 
881
881
  return state->gc_tracepoint;
882
882
  }
@@ -902,7 +902,7 @@ static void on_gc_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused) {
902
902
  int event = rb_tracearg_event_flag(rb_tracearg_from_tracepoint(tracepoint_data));
903
903
  if (event != RUBY_INTERNAL_EVENT_GC_ENTER && event != RUBY_INTERNAL_EVENT_GC_EXIT) return; // Unknown event
904
904
 
905
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
905
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
906
906
 
907
907
  // This should not happen in a normal situation because the tracepoint is always enabled after the instance is set
908
908
  // and disabled before it is cleared, but just in case...
@@ -926,7 +926,7 @@ static void on_gc_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused) {
926
926
  }
927
927
 
928
928
  static void after_gc_from_postponed_job(DDTRACE_UNUSED void *_unused) {
929
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
929
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
930
930
 
931
931
  // This can potentially happen if the CpuAndWallTimeWorker was stopped while the postponed job was waiting to be executed; nothing to do
932
932
  if (state == NULL) return;
@@ -981,8 +981,8 @@ static VALUE _native_simulate_sample_from_postponed_job(DDTRACE_UNUSED VALUE sel
981
981
  // In the future, if we add more other components with tracepoints, we will need to coordinate stopping all such
982
982
  // tracepoints before doing the other cleaning steps.
983
983
  static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE instance) {
984
- struct cpu_and_wall_time_worker_state *state;
985
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
984
+ cpu_and_wall_time_worker_state *state;
985
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
986
986
 
987
987
  // Disable all tracepoints, so that there are no more attempts to mutate the profile
988
988
  disable_tracepoints(state);
@@ -1000,8 +1000,8 @@ static VALUE _native_is_sigprof_blocked_in_current_thread(DDTRACE_UNUSED VALUE s
1000
1000
  }
1001
1001
 
1002
1002
  static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance) {
1003
- struct cpu_and_wall_time_worker_state *state;
1004
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1003
+ cpu_and_wall_time_worker_state *state;
1004
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1005
1005
 
1006
1006
  unsigned long total_cpu_samples_attempted = state->stats.cpu_sampled + state->stats.cpu_skipped;
1007
1007
  VALUE effective_cpu_sample_rate =
@@ -1059,14 +1059,14 @@ static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance) {
1059
1059
  }
1060
1060
 
1061
1061
  static VALUE _native_stats_reset_not_thread_safe(DDTRACE_UNUSED VALUE self, VALUE instance) {
1062
- struct cpu_and_wall_time_worker_state *state;
1063
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1062
+ cpu_and_wall_time_worker_state *state;
1063
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1064
1064
  reset_stats_not_thread_safe(state);
1065
1065
  return Qnil;
1066
1066
  }
1067
1067
 
1068
1068
  void *simulate_sampling_signal_delivery(DDTRACE_UNUSED void *_unused) {
1069
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1069
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1070
1070
 
1071
1071
  // This can potentially happen if the CpuAndWallTimeWorker was stopped while the IdleSamplingHelper was trying to execute this action
1072
1072
  if (state == NULL) return NULL;
@@ -1082,7 +1082,7 @@ void *simulate_sampling_signal_delivery(DDTRACE_UNUSED void *_unused) {
1082
1082
 
1083
1083
  static void grab_gvl_and_sample(void) { rb_thread_call_with_gvl(simulate_sampling_signal_delivery, NULL); }
1084
1084
 
1085
- static void reset_stats_not_thread_safe(struct cpu_and_wall_time_worker_state *state) {
1085
+ static void reset_stats_not_thread_safe(cpu_and_wall_time_worker_state *state) {
1086
1086
  // NOTE: This is not really thread safe so ongoing sampling operations that are concurrent with a reset can have their stats:
1087
1087
  // * Lost (writes after stats retrieval but before reset).
1088
1088
  // * Included in the previous stats window (writes before stats retrieval and reset).
@@ -1116,7 +1116,7 @@ static void sleep_for(uint64_t time_ns) {
1116
1116
  }
1117
1117
 
1118
1118
  static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self) {
1119
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state;
1119
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state;
1120
1120
 
1121
1121
  bool are_allocations_being_tracked = state != NULL && state->allocation_profiling_enabled && state->allocation_counting_enabled;
1122
1122
 
@@ -1149,7 +1149,7 @@ static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self) {
1149
1149
  // call `rb_tracearg_from_tracepoint(anything)` anywhere during this function or its callees to get the data, so that's
1150
1150
  // why it's not being passed as an argument.
1151
1151
  static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *unused2) {
1152
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1152
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1153
1153
 
1154
1154
  // This should not happen in a normal situation because the tracepoint is always enabled after the instance is set
1155
1155
  // and disabled before it is cleared, but just in case...
@@ -1171,6 +1171,16 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
1171
1171
  return;
1172
1172
  }
1173
1173
 
1174
+ // If Ruby is in the middle of raising an exception, we don't want to try to sample. This is because if we accidentally
1175
+ // trigger an exception inside the profiler code, bad things will happen (specifically, Ruby will try to kill off the
1176
+ // thread even though we may try to catch the exception).
1177
+ //
1178
+ // Note that "in the middle of raising an exception" means the exception itself has already been allocated.
1179
+ // What's getting allocated now is probably the backtrace objects (@ivoanjo or at least that's what I've observed)
1180
+ if (is_raised_flag_set(rb_thread_current())) {
1181
+ return;
1182
+ }
1183
+
1174
1184
  // Hot path: Dynamic sampling rate is usually enabled and the sampling decision is usually false
1175
1185
  if (RB_LIKELY(state->dynamic_sampling_rate_enabled && !discrete_dynamic_sampler_should_sample(&state->allocation_sampler))) {
1176
1186
  state->stats.allocation_skipped++;
@@ -1225,7 +1235,7 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
1225
1235
  state->during_sample = false;
1226
1236
  }
1227
1237
 
1228
- static void disable_tracepoints(struct cpu_and_wall_time_worker_state *state) {
1238
+ static void disable_tracepoints(cpu_and_wall_time_worker_state *state) {
1229
1239
  if (state->gc_tracepoint != Qnil) {
1230
1240
  rb_tracepoint_disable(state->gc_tracepoint);
1231
1241
  }
@@ -1254,7 +1264,7 @@ static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self) {
1254
1264
  }
1255
1265
 
1256
1266
  static VALUE rescued_sample_allocation(DDTRACE_UNUSED VALUE unused) {
1257
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1267
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1258
1268
 
1259
1269
  // This should not happen in a normal situation because on_newobj_event already checked for this, but just in case...
1260
1270
  if (state == NULL) return Qnil;
@@ -1283,7 +1293,7 @@ static VALUE rescued_sample_allocation(DDTRACE_UNUSED VALUE unused) {
1283
1293
  return Qnil;
1284
1294
  }
1285
1295
 
1286
- static void delayed_error(struct cpu_and_wall_time_worker_state *state, const char *error) {
1296
+ static void delayed_error(cpu_and_wall_time_worker_state *state, const char *error) {
1287
1297
  // If we can't raise an immediate exception at the calling site, use the asynchronous flow through the main worker loop.
1288
1298
  stop_state(state, rb_exc_new_cstr(rb_eRuntimeError, error));
1289
1299
  }
@@ -1291,8 +1301,8 @@ static void delayed_error(struct cpu_and_wall_time_worker_state *state, const ch
1291
1301
  static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg) {
1292
1302
  ENFORCE_TYPE(error_msg, T_STRING);
1293
1303
 
1294
- struct cpu_and_wall_time_worker_state *state;
1295
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1304
+ cpu_and_wall_time_worker_state *state;
1305
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1296
1306
 
1297
1307
  delayed_error(state, rb_string_value_cstr(&error_msg));
1298
1308
 
@@ -1345,7 +1355,7 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
1345
1355
  rb_postponed_job_register_one(0, after_gvl_running_from_postponed_job, NULL);
1346
1356
  #endif
1347
1357
  } else if (result == ON_GVL_RUNNING_DONT_SAMPLE) {
1348
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1358
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1349
1359
 
1350
1360
  if (state == NULL) return; // This should not happen, but just in case...
1351
1361
 
@@ -1358,7 +1368,7 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
1358
1368
  }
1359
1369
 
1360
1370
  static void after_gvl_running_from_postponed_job(DDTRACE_UNUSED void *_unused) {
1361
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1371
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1362
1372
 
1363
1373
  // This can potentially happen if the CpuAndWallTimeWorker was stopped while the postponed job was waiting to be executed; nothing to do
1364
1374
  if (state == NULL) return;
@@ -1372,8 +1382,8 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
1372
1382
  }
1373
1383
 
1374
1384
  static VALUE rescued_after_gvl_running_from_postponed_job(VALUE self_instance) {
1375
- struct cpu_and_wall_time_worker_state *state;
1376
- TypedData_Get_Struct(self_instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1385
+ cpu_and_wall_time_worker_state *state;
1386
+ TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1377
1387
 
1378
1388
  long wall_time_ns_before_sample = monotonic_wall_time_now_ns(RAISE_ON_FAILURE);
1379
1389
  thread_context_collector_sample_after_gvl_running(state->thread_context_collector_instance, rb_thread_current(), wall_time_ns_before_sample);
@@ -1394,8 +1404,8 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
1394
1404
  }
1395
1405
 
1396
1406
  static VALUE _native_gvl_profiling_hook_active(DDTRACE_UNUSED VALUE self, VALUE instance) {
1397
- struct cpu_and_wall_time_worker_state *state;
1398
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1407
+ cpu_and_wall_time_worker_state *state;
1408
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1399
1409
 
1400
1410
  return state->gvl_profiling_hook != NULL ? Qtrue : Qfalse;
1401
1411
  }
@@ -333,7 +333,7 @@ static VALUE _native_should_sample(VALUE self, VALUE now);
333
333
  static VALUE _native_after_sample(VALUE self, VALUE now);
334
334
  static VALUE _native_state_snapshot(VALUE self);
335
335
 
336
- typedef struct sampler_state {
336
+ typedef struct {
337
337
  discrete_dynamic_sampler sampler;
338
338
  } sampler_state;
339
339
 
@@ -16,7 +16,7 @@
16
16
  // every event and is thus, in theory, susceptible to some pattern
17
17
  // biases. In practice, the dynamic readjustment of sampling interval
18
18
  // and randomized starting point should help with avoiding heavy biases.
19
- typedef struct discrete_dynamic_sampler {
19
+ typedef struct {
20
20
  // --- Config ---
21
21
  // Name of this sampler for debug logs.
22
22
  const char *debug_name;
@@ -21,15 +21,15 @@
21
21
  typedef enum { ACTION_WAIT, ACTION_RUN, ACTION_STOP } action;
22
22
 
23
23
  // Contains state for a single CpuAndWallTimeWorker instance
24
- struct idle_sampling_loop_state {
24
+ typedef struct {
25
25
  pthread_mutex_t wakeup_mutex;
26
26
  pthread_cond_t wakeup;
27
27
  action requested_action;
28
28
  void (*run_action_function)(void);
29
- };
29
+ } idle_sampling_loop_state;
30
30
 
31
31
  static VALUE _native_new(VALUE klass);
32
- static void reset_state(struct idle_sampling_loop_state *state);
32
+ static void reset_state(idle_sampling_loop_state *state);
33
33
  static VALUE _native_idle_sampling_loop(DDTRACE_UNUSED VALUE self, VALUE self_instance);
34
34
  static VALUE _native_stop(DDTRACE_UNUSED VALUE self, VALUE self_instance);
35
35
  static void *run_idle_sampling_loop(void *state_ptr);
@@ -62,7 +62,7 @@ void collectors_idle_sampling_helper_init(VALUE profiling_module) {
62
62
  rb_define_singleton_method(testing_module, "_native_idle_sampling_helper_request_action", _native_idle_sampling_helper_request_action, 1);
63
63
  }
64
64
 
65
- // This structure is used to define a Ruby object that stores a pointer to a struct idle_sampling_loop_state
65
+ // This structure is used to define a Ruby object that stores a pointer to a idle_sampling_loop_state
66
66
  // See also https://github.com/ruby/ruby/blob/master/doc/extension.rdoc for how this works
67
67
  static const rb_data_type_t idle_sampling_helper_typed_data = {
68
68
  .wrap_struct_name = "Datadog::Profiling::Collectors::IdleSamplingHelper",
@@ -76,7 +76,7 @@ static const rb_data_type_t idle_sampling_helper_typed_data = {
76
76
  };
77
77
 
78
78
  static VALUE _native_new(VALUE klass) {
79
- struct idle_sampling_loop_state *state = ruby_xcalloc(1, sizeof(struct idle_sampling_loop_state));
79
+ idle_sampling_loop_state *state = ruby_xcalloc(1, sizeof(idle_sampling_loop_state));
80
80
 
81
81
  // Note: Any exceptions raised from this note until the TypedData_Wrap_Struct call will lead to the state memory
82
82
  // being leaked.
@@ -90,7 +90,7 @@ static VALUE _native_new(VALUE klass) {
90
90
  return TypedData_Wrap_Struct(klass, &idle_sampling_helper_typed_data, state);
91
91
  }
92
92
 
93
- static void reset_state(struct idle_sampling_loop_state *state) {
93
+ static void reset_state(idle_sampling_loop_state *state) {
94
94
  state->wakeup_mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
95
95
  state->wakeup = (pthread_cond_t) PTHREAD_COND_INITIALIZER;
96
96
  state->requested_action = ACTION_WAIT;
@@ -101,8 +101,8 @@ static void reset_state(struct idle_sampling_loop_state *state) {
101
101
  // a pristine state before recreating the worker thread (this includes resetting the mutex in case it was left
102
102
  // locked halfway through the VM forking)
103
103
  static VALUE _native_reset(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
104
- struct idle_sampling_loop_state *state;
105
- TypedData_Get_Struct(self_instance, struct idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
104
+ idle_sampling_loop_state *state;
105
+ TypedData_Get_Struct(self_instance, idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
106
106
 
107
107
  reset_state(state);
108
108
 
@@ -110,8 +110,8 @@ static VALUE _native_reset(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
110
110
  }
111
111
 
112
112
  static VALUE _native_idle_sampling_loop(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
113
- struct idle_sampling_loop_state *state;
114
- TypedData_Get_Struct(self_instance, struct idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
113
+ idle_sampling_loop_state *state;
114
+ TypedData_Get_Struct(self_instance, idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
115
115
 
116
116
  // Release GVL and run the loop waiting for requests
117
117
  rb_thread_call_without_gvl(run_idle_sampling_loop, state, interrupt_idle_sampling_loop, state);
@@ -120,7 +120,7 @@ static VALUE _native_idle_sampling_loop(DDTRACE_UNUSED VALUE self, VALUE self_in
120
120
  }
121
121
 
122
122
  static void *run_idle_sampling_loop(void *state_ptr) {
123
- struct idle_sampling_loop_state *state = (struct idle_sampling_loop_state *) state_ptr;
123
+ idle_sampling_loop_state *state = (idle_sampling_loop_state *) state_ptr;
124
124
  int error = 0;
125
125
 
126
126
  while (true) {
@@ -164,7 +164,7 @@ static void *run_idle_sampling_loop(void *state_ptr) {
164
164
  }
165
165
 
166
166
  static void interrupt_idle_sampling_loop(void *state_ptr) {
167
- struct idle_sampling_loop_state *state = (struct idle_sampling_loop_state *) state_ptr;
167
+ idle_sampling_loop_state *state = (idle_sampling_loop_state *) state_ptr;
168
168
  int error = 0;
169
169
 
170
170
  // Note about the error handling in this situation: Something bad happening at this stage is really really awkward to
@@ -189,8 +189,8 @@ static void interrupt_idle_sampling_loop(void *state_ptr) {
189
189
  }
190
190
 
191
191
  static VALUE _native_stop(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
192
- struct idle_sampling_loop_state *state;
193
- TypedData_Get_Struct(self_instance, struct idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
192
+ idle_sampling_loop_state *state;
193
+ TypedData_Get_Struct(self_instance, idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
194
194
 
195
195
  ENFORCE_SUCCESS_GVL(pthread_mutex_lock(&state->wakeup_mutex));
196
196
  state->requested_action = ACTION_STOP;
@@ -204,12 +204,12 @@ static VALUE _native_stop(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
204
204
 
205
205
  // Assumption: Function gets called without the global VM lock
206
206
  void idle_sampling_helper_request_action(VALUE self_instance, void (*run_action_function)(void)) {
207
- struct idle_sampling_loop_state *state;
207
+ idle_sampling_loop_state *state;
208
208
  if (!rb_typeddata_is_kind_of(self_instance, &idle_sampling_helper_typed_data)) {
209
209
  grab_gvl_and_raise(rb_eTypeError, "Wrong argument for idle_sampling_helper_request_action");
210
210
  }
211
211
  // This should never fail the the above check passes
212
- TypedData_Get_Struct(self_instance, struct idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
212
+ TypedData_Get_Struct(self_instance, idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
213
213
 
214
214
  ENFORCE_SUCCESS_NO_GVL(pthread_mutex_lock(&state->wakeup_mutex));
215
215
  if (state->requested_action == ACTION_WAIT) {