datadog 2.44.0 → 2.45.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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -1
  3. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +114 -141
  4. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -5
  5. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +0 -2
  6. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +13 -13
  7. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.h +5 -1
  8. data/ext/datadog_profiling_native_extension/collectors_stack.c +1 -0
  9. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +106 -103
  10. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +3 -3
  11. data/ext/datadog_profiling_native_extension/extconf.rb +2 -0
  12. data/ext/datadog_profiling_native_extension/heap_recorder.c +2 -2
  13. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +98 -54
  14. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +5 -2
  15. data/ext/datadog_profiling_native_extension/profiling.c +21 -23
  16. data/ext/datadog_profiling_native_extension/ruby_helpers.c +3 -1
  17. data/ext/datadog_profiling_native_extension/ruby_helpers.h +4 -0
  18. data/ext/datadog_profiling_native_extension/setup_signal_handler.c +0 -2
  19. data/ext/datadog_profiling_native_extension/stack_recorder.c +6 -24
  20. data/ext/datadog_profiling_native_extension/stack_recorder.h +0 -1
  21. data/ext/datadog_profiling_native_extension/time_helpers.c +2 -4
  22. data/ext/datadog_profiling_native_extension/time_helpers.h +10 -11
  23. data/ext/libdatadog_api/trace_exporter.c +77 -11
  24. data/ext/libdatadog_extconf_helpers.rb +1 -1
  25. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +5 -0
  26. data/lib/datadog/profiling/component.rb +2 -3
  27. data/lib/datadog/profiling/exporter.rb +7 -5
  28. data/lib/datadog/tracing/component.rb +1 -1
  29. data/lib/datadog/tracing/configuration/settings.rb +3 -2
  30. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +6 -3
  31. data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -0
  32. data/lib/datadog/tracing/transport/native.rb +22 -21
  33. data/lib/datadog/version.rb +1 -1
  34. metadata +5 -5
@@ -53,8 +53,6 @@ void gc_profiling_init(void) {
53
53
  shady_sym = ID2SYM(rb_intern_const("shady"));
54
54
  force_sym = ID2SYM(rb_intern_const("force"));
55
55
  oldmalloc_sym = ID2SYM(rb_intern_const("oldmalloc"));
56
- state_sym = ID2SYM(rb_intern_const("state"));
57
- none_sym = ID2SYM(rb_intern_const("none"));
58
56
  }
59
57
 
60
58
  bool gc_profiling_has_major_gc_finished(void) {
@@ -22,12 +22,12 @@
22
22
  typedef enum { ACTION_WAIT, ACTION_RUN, ACTION_STOP } action;
23
23
 
24
24
  // Contains state for a single CpuAndWallTimeWorker instance
25
- typedef struct {
25
+ struct idle_sampling_loop_state {
26
26
  pthread_mutex_t wakeup_mutex;
27
27
  pthread_cond_t wakeup;
28
28
  action requested_action;
29
29
  void (*run_action_function)(void);
30
- } idle_sampling_loop_state;
30
+ };
31
31
 
32
32
  static VALUE _native_new(VALUE klass);
33
33
  static void reset_state(idle_sampling_loop_state *state);
@@ -39,7 +39,7 @@ static void *run_idle_sampling_loop(void *state_ptr);
39
39
  static void interrupt_idle_sampling_loop(void *state_ptr);
40
40
  static VALUE _native_reset(DDTRACE_UNUSED VALUE self, VALUE self_instance);
41
41
  static VALUE _native_idle_sampling_helper_request_action(DDTRACE_UNUSED VALUE self, VALUE self_instance);
42
- static void *request_testing_action(void *self_instance_ptr);
42
+ static void *request_testing_action(void *state_ptr);
43
43
  static void grab_gvl_and_run_testing_action(void);
44
44
  static void *run_testing_action(DDTRACE_UNUSED void *unused);
45
45
 
@@ -215,15 +215,14 @@ static VALUE _native_stop(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
215
215
  return Qtrue;
216
216
  }
217
217
 
218
- // Assumption: Function gets called without the global VM lock
219
- void idle_sampling_helper_request_action(VALUE self_instance, void (*run_action_function)(void)) {
218
+ idle_sampling_loop_state *idle_sampling_helper_get_state(VALUE self_instance) {
220
219
  idle_sampling_loop_state *state;
221
- if (!rb_typeddata_is_kind_of(self_instance, &idle_sampling_helper_typed_data)) {
222
- grab_gvl_and_raise(rb_eTypeError, "Wrong argument for idle_sampling_helper_request_action");
223
- }
224
- // This should never fail when the above check passes
225
220
  TypedData_Get_Struct(self_instance, idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
221
+ return state;
222
+ }
226
223
 
224
+ // Called without the GVL, so we access native state directly: touching the Ruby self_instance is unsafe during GC compaction.
225
+ void idle_sampling_helper_request_action(idle_sampling_loop_state *state, void (*run_action_function)(void)) {
227
226
  ENFORCE_SUCCESS_NO_GVL(pthread_mutex_lock(&state->wakeup_mutex));
228
227
  if (state->requested_action == ACTION_WAIT) {
229
228
  state->requested_action = ACTION_RUN;
@@ -238,13 +237,14 @@ void idle_sampling_helper_request_action(VALUE self_instance, void (*run_action_
238
237
  // Because the idle_sampling_helper_request_action is built to be called without the global VM lock, here we release it
239
238
  // to be able to call that API.
240
239
  static VALUE _native_idle_sampling_helper_request_action(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
241
- rb_thread_call_without_gvl(request_testing_action, (void *) self_instance, NULL, NULL);
240
+ idle_sampling_loop_state *state = idle_sampling_helper_get_state(self_instance);
241
+ rb_thread_call_without_gvl(request_testing_action, state, NULL, NULL);
242
+ RB_GC_GUARD(self_instance);
242
243
  return Qtrue;
243
244
  }
244
245
 
245
- static void *request_testing_action(void *self_instance_ptr) {
246
- VALUE self_instance = (VALUE) self_instance_ptr;
247
- idle_sampling_helper_request_action(self_instance, grab_gvl_and_run_testing_action);
246
+ static void *request_testing_action(void *state_ptr) {
247
+ idle_sampling_helper_request_action(state_ptr, grab_gvl_and_run_testing_action);
248
248
  return NULL;
249
249
  }
250
250
 
@@ -1,3 +1,7 @@
1
1
  #pragma once
2
2
 
3
- void idle_sampling_helper_request_action(VALUE self_instance, void (*run_action_function)(void));
3
+ typedef struct idle_sampling_loop_state idle_sampling_loop_state;
4
+
5
+ // Must be called with the GVL held; keep self_instance alive while using the returned pointer.
6
+ idle_sampling_loop_state *idle_sampling_helper_get_state(VALUE self_instance);
7
+ void idle_sampling_helper_request_action(idle_sampling_loop_state *state, void (*run_action_function)(void));
@@ -641,6 +641,7 @@ void record_placeholder_stack(
641
641
  );
642
642
  }
643
643
 
644
+ // Also called from a signal handler or during GC; check callers' safety requirements before changing this function.
644
645
  bool prepare_sample_thread(VALUE thread, sampling_buffer *buffer) {
645
646
  // While the signal handler checks if there's GC going on, it's actually possible for `sampling_buffer_mark` to
646
647
  // still run outside of GC (see comments on that function) and thus we guard for it here.