datadog 2.7.1 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +69 -1
- data/ext/datadog_profiling_native_extension/clock_id.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +64 -54
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +16 -16
- data/ext/datadog_profiling_native_extension/collectors_stack.c +7 -7
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +259 -132
- data/ext/datadog_profiling_native_extension/extconf.rb +0 -8
- data/ext/datadog_profiling_native_extension/heap_recorder.c +11 -89
- data/ext/datadog_profiling_native_extension/heap_recorder.h +1 -1
- data/ext/datadog_profiling_native_extension/http_transport.c +4 -4
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +4 -1
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -1
- data/ext/datadog_profiling_native_extension/profiling.c +10 -8
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +8 -8
- data/ext/datadog_profiling_native_extension/stack_recorder.c +54 -88
- data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -1
- data/ext/datadog_profiling_native_extension/time_helpers.h +1 -1
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
- data/ext/libdatadog_api/crashtracker.c +3 -0
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +355 -157
- data/lib/datadog/appsec/assets/waf_rules/strict.json +62 -32
- data/lib/datadog/appsec/component.rb +1 -8
- data/lib/datadog/appsec/context.rb +54 -0
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +73 -0
- data/lib/datadog/appsec/contrib/active_record/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +53 -0
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +6 -6
- data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +4 -4
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +19 -28
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +5 -5
- data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +64 -96
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +10 -10
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +5 -5
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +6 -6
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +43 -49
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +21 -32
- data/lib/datadog/appsec/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +6 -6
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +41 -63
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +2 -2
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +5 -5
- data/lib/datadog/appsec/event.rb +6 -6
- data/lib/datadog/appsec/ext.rb +3 -1
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +22 -32
- data/lib/datadog/appsec/monitor/reactive/set_user.rb +5 -5
- data/lib/datadog/appsec/processor/context.rb +2 -2
- data/lib/datadog/appsec/processor/rule_loader.rb +0 -3
- data/lib/datadog/appsec/remote.rb +1 -3
- data/lib/datadog/appsec/response.rb +7 -11
- data/lib/datadog/appsec.rb +6 -5
- data/lib/datadog/auto_instrument.rb +3 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +39 -11
- data/lib/datadog/core/configuration/components.rb +20 -2
- data/lib/datadog/core/configuration/settings.rb +10 -0
- data/lib/datadog/core/configuration.rb +10 -2
- data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
- data/lib/datadog/core/crashtracking/component.rb +1 -3
- data/lib/datadog/core/remote/client/capabilities.rb +6 -0
- data/lib/datadog/core/remote/client.rb +65 -59
- data/lib/datadog/core/telemetry/component.rb +9 -3
- data/lib/datadog/core/telemetry/event.rb +87 -3
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- data/lib/datadog/core/telemetry/logging.rb +2 -2
- data/lib/datadog/core/telemetry/metric.rb +22 -0
- data/lib/datadog/core/telemetry/worker.rb +33 -0
- data/lib/datadog/di/base.rb +115 -0
- data/lib/datadog/di/code_tracker.rb +11 -7
- data/lib/datadog/di/component.rb +21 -11
- data/lib/datadog/di/configuration/settings.rb +11 -1
- data/lib/datadog/di/contrib/active_record.rb +1 -0
- data/lib/datadog/di/contrib/railtie.rb +15 -0
- data/lib/datadog/di/contrib.rb +26 -0
- data/lib/datadog/di/error.rb +5 -0
- data/lib/datadog/di/instrumenter.rb +111 -20
- data/lib/datadog/di/preload.rb +18 -0
- data/lib/datadog/di/probe.rb +11 -1
- data/lib/datadog/di/probe_builder.rb +1 -0
- data/lib/datadog/di/probe_manager.rb +8 -5
- data/lib/datadog/di/probe_notification_builder.rb +27 -7
- data/lib/datadog/di/probe_notifier_worker.rb +5 -6
- data/lib/datadog/di/remote.rb +124 -0
- data/lib/datadog/di/serializer.rb +14 -7
- data/lib/datadog/di/transport.rb +3 -5
- data/lib/datadog/di/utils.rb +7 -0
- data/lib/datadog/di.rb +23 -62
- data/lib/datadog/kit/appsec/events.rb +3 -3
- data/lib/datadog/kit/identity.rb +4 -4
- data/lib/datadog/profiling/component.rb +59 -69
- data/lib/datadog/profiling/http_transport.rb +1 -26
- data/lib/datadog/tracing/configuration/settings.rb +4 -8
- data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
- data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_record/integration.rb +6 -2
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +16 -4
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
- data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +4 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
- data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
- data/lib/datadog/tracing/span.rb +12 -4
- data/lib/datadog/tracing/span_event.rb +123 -3
- data/lib/datadog/tracing/span_operation.rb +6 -0
- data/lib/datadog/tracing/transport/serializable_trace.rb +24 -6
- data/lib/datadog/version.rb +2 -2
- data/lib/datadog.rb +3 -0
- metadata +30 -17
- data/lib/datadog/appsec/processor/actions.rb +0 -49
- data/lib/datadog/appsec/reactive/operation.rb +0 -68
- data/lib/datadog/appsec/scope.rb +0 -58
- data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
@@ -170,11 +170,6 @@ $defs << "-DNO_THREAD_TID" if RUBY_VERSION < "3.1"
|
|
170
170
|
# On older Rubies, there was no jit_return member on the rb_control_frame_t struct
|
171
171
|
$defs << "-DNO_JIT_RETURN" if RUBY_VERSION < "3.1"
|
172
172
|
|
173
|
-
# On older Rubies, rb_gc_force_recycle allowed to free objects in a way that
|
174
|
-
# would be invisible to free tracepoints, finalizers and without cleaning
|
175
|
-
# obj_to_id_tbl mappings.
|
176
|
-
$defs << "-DHAVE_WORKING_RB_GC_FORCE_RECYCLE" if RUBY_VERSION < "3.1"
|
177
|
-
|
178
173
|
# On older Rubies, there are no Ractors
|
179
174
|
$defs << "-DNO_RACTORS" if RUBY_VERSION < "3"
|
180
175
|
|
@@ -184,9 +179,6 @@ $defs << "-DNO_IMEMO_NAME" if RUBY_VERSION < "3"
|
|
184
179
|
# On older Rubies, objects would not move
|
185
180
|
$defs << "-DNO_T_MOVED" if RUBY_VERSION < "2.7"
|
186
181
|
|
187
|
-
# On older Rubies, there was no RUBY_SEEN_OBJ_ID flag
|
188
|
-
$defs << "-DNO_SEEN_OBJ_ID_FLAG" if RUBY_VERSION < "2.7"
|
189
|
-
|
190
182
|
# On older Rubies, rb_global_vm_lock_struct did not include the owner field
|
191
183
|
$defs << "-DNO_GVL_OWNER" if RUBY_VERSION < "2.6"
|
192
184
|
|
@@ -7,10 +7,6 @@
|
|
7
7
|
#include "libdatadog_helpers.h"
|
8
8
|
#include "time_helpers.h"
|
9
9
|
|
10
|
-
#if (defined(HAVE_WORKING_RB_GC_FORCE_RECYCLE) && ! defined(NO_SEEN_OBJ_ID_FLAG))
|
11
|
-
#define CAN_APPLY_GC_FORCE_RECYCLE_BUG_WORKAROUND
|
12
|
-
#endif
|
13
|
-
|
14
10
|
// Minimum age (in GC generations) of heap objects we want to include in heap
|
15
11
|
// recorder iterations. Object with age 0 represent objects that have yet to undergo
|
16
12
|
// a GC and, thus, may just be noise/trash at instant of iteration and are usually not
|
@@ -123,9 +119,6 @@ typedef struct {
|
|
123
119
|
// Pointer to the (potentially partial) object_record containing metadata about an ongoing recording.
|
124
120
|
// When NULL, this symbolizes an unstarted/invalid recording.
|
125
121
|
object_record *object_record;
|
126
|
-
// A flag to track whether we had to force set the RUBY_FL_SEEN_OBJ_ID flag on this object
|
127
|
-
// as part of our workaround around rb_gc_force_recycle issues.
|
128
|
-
bool did_recycle_workaround;
|
129
122
|
} recording;
|
130
123
|
|
131
124
|
struct heap_recorder {
|
@@ -342,46 +335,12 @@ void start_heap_allocation_recording(heap_recorder *heap_recorder, VALUE new_obj
|
|
342
335
|
rb_raise(rb_eRuntimeError, "Detected a bignum object id. These are not supported by heap profiling.");
|
343
336
|
}
|
344
337
|
|
345
|
-
bool did_recycle_workaround = false;
|
346
|
-
|
347
|
-
#ifdef CAN_APPLY_GC_FORCE_RECYCLE_BUG_WORKAROUND
|
348
|
-
// If we are in a ruby version that has a working rb_gc_force_recycle implementation,
|
349
|
-
// its usage may lead to an object being re-used outside of the typical GC cycle.
|
350
|
-
//
|
351
|
-
// This re-use is in theory invisible to us unless we're lucky enough to sample both
|
352
|
-
// the original object and the replacement that uses the recycled slot.
|
353
|
-
//
|
354
|
-
// In practice, we've observed (https://github.com/DataDog/dd-trace-rb/pull/3366)
|
355
|
-
// that non-noop implementations of rb_gc_force_recycle have an implementation bug
|
356
|
-
// which results in the object that re-used the recycled slot inheriting the same
|
357
|
-
// object id without setting the FL_SEEN_OBJ_ID flag. We rely on this knowledge to
|
358
|
-
// "observe" implicit frees when an object we are tracking is force-recycled.
|
359
|
-
//
|
360
|
-
// However, it may happen that we start tracking a new object and that object was
|
361
|
-
// allocated on a recycled slot. Due to the bug, this object would be missing the
|
362
|
-
// FL_SEEN_OBJ_ID flag even though it was not recycled itself. If we left it be,
|
363
|
-
// when we're doing our liveness check, the absence of the flag would trigger our
|
364
|
-
// implicit free workaround and the object would be inferred as recycled even though
|
365
|
-
// it might still be alive.
|
366
|
-
//
|
367
|
-
// Thus, if we detect that this new allocation is already missing the flag at the start
|
368
|
-
// of the heap allocation recording, we force-set it. This should be safe since we
|
369
|
-
// just called rb_obj_id on it above and the expectation is that any flaggable object
|
370
|
-
// that goes through it ends up with the flag set (as evidenced by the GC_ASSERT
|
371
|
-
// lines in https://github.com/ruby/ruby/blob/4a8d7246d15b2054eacb20f8ab3d29d39a3e7856/gc.c#L4050C14-L4050C14).
|
372
|
-
if (RB_FL_ABLE(new_obj) && !RB_FL_TEST(new_obj, RUBY_FL_SEEN_OBJ_ID)) {
|
373
|
-
RB_FL_SET(new_obj, RUBY_FL_SEEN_OBJ_ID);
|
374
|
-
did_recycle_workaround = true;
|
375
|
-
}
|
376
|
-
#endif
|
377
|
-
|
378
338
|
heap_recorder->active_recording = (recording) {
|
379
339
|
.object_record = object_record_new(FIX2LONG(ruby_obj_id), NULL, (live_object_data) {
|
380
340
|
.weight = weight * heap_recorder->sample_rate,
|
381
341
|
.class = alloc_class != NULL ? string_from_char_slice(*alloc_class) : NULL,
|
382
342
|
.alloc_gen = rb_gc_count(),
|
383
|
-
|
384
|
-
.did_recycle_workaround = did_recycle_workaround,
|
343
|
+
}),
|
385
344
|
};
|
386
345
|
}
|
387
346
|
|
@@ -685,41 +644,6 @@ static int st_object_record_update(st_data_t key, st_data_t value, st_data_t ext
|
|
685
644
|
|
686
645
|
// If we got this far, then we found a valid live object for the tracked id.
|
687
646
|
|
688
|
-
#ifdef CAN_APPLY_GC_FORCE_RECYCLE_BUG_WORKAROUND
|
689
|
-
// If we are in a ruby version that has a working rb_gc_force_recycle implementation,
|
690
|
-
// its usage may lead to an object being re-used outside of the typical GC cycle.
|
691
|
-
//
|
692
|
-
// This re-use is in theory invisible to us and would mean that the ref from which we
|
693
|
-
// collected the object_record metadata may not be the same as the current ref and
|
694
|
-
// thus any further reporting would be innacurately attributed to stale metadata.
|
695
|
-
//
|
696
|
-
// In practice, there is a way for us to notice that this happened because of a bug
|
697
|
-
// in the implementation of rb_gc_force_recycle. Our heap profiler relies on object
|
698
|
-
// ids and id2ref to detect whether objects are still alive. Turns out that when an
|
699
|
-
// object with an id is re-used via rb_gc_force_recycle, it will "inherit" the ID
|
700
|
-
// of the old object but it will NOT have the FL_SEEN_OBJ_ID as per the experiment
|
701
|
-
// in https://github.com/DataDog/dd-trace-rb/pull/3360#discussion_r1442823517
|
702
|
-
//
|
703
|
-
// Thus, if we detect that the ref we just resolved above is missing this flag, we can
|
704
|
-
// safely say re-use happened and thus treat it as an implicit free of the object
|
705
|
-
// we were tracking (the original one which got recycled).
|
706
|
-
if (RB_FL_ABLE(ref) && !RB_FL_TEST(ref, RUBY_FL_SEEN_OBJ_ID)) {
|
707
|
-
|
708
|
-
// NOTE: We don't really need to set this flag for heap recorder to work correctly
|
709
|
-
// but doing so partially mitigates a bug in runtimes with working rb_gc_force_recycle
|
710
|
-
// which leads to broken invariants and leaking of entries in obj_to_id and id_to_obj
|
711
|
-
// tables in objspace. We already do the same thing when we sample a recycled object,
|
712
|
-
// here we apply it as well to objects that replace recycled objects that were being
|
713
|
-
// tracked. More details in https://github.com/DataDog/dd-trace-rb/pull/3366
|
714
|
-
RB_FL_SET(ref, RUBY_FL_SEEN_OBJ_ID);
|
715
|
-
|
716
|
-
on_committed_object_record_cleanup(recorder, record);
|
717
|
-
recorder->stats_last_update.objects_dead++;
|
718
|
-
return ST_DELETE;
|
719
|
-
}
|
720
|
-
|
721
|
-
#endif
|
722
|
-
|
723
647
|
if (
|
724
648
|
recorder->size_enabled &&
|
725
649
|
recorder->update_include_old && // We only update sizes when doing a full update
|
@@ -732,6 +656,10 @@ static int st_object_record_update(st_data_t key, st_data_t value, st_data_t ext
|
|
732
656
|
record->object_data.is_frozen = RB_OBJ_FROZEN(ref);
|
733
657
|
}
|
734
658
|
|
659
|
+
// Ensure that ref is kept on the stack so the Ruby garbage collector does not try to clean up the object before this
|
660
|
+
// point.
|
661
|
+
RB_GC_GUARD(ref);
|
662
|
+
|
735
663
|
recorder->stats_last_update.objects_alive++;
|
736
664
|
if (record->object_data.is_frozen) {
|
737
665
|
recorder->stats_last_update.objects_frozen++;
|
@@ -803,18 +731,12 @@ static int update_object_record_entry(DDTRACE_UNUSED st_data_t *key, st_data_t *
|
|
803
731
|
object_record *new_object_record = recording.object_record;
|
804
732
|
if (existing) {
|
805
733
|
object_record *existing_record = (object_record*) (*value);
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
// This is not supposed to happen, raising...
|
813
|
-
VALUE existing_inspect = object_record_inspect(existing_record);
|
814
|
-
VALUE new_inspect = object_record_inspect(new_object_record);
|
815
|
-
rb_raise(rb_eRuntimeError, "Object ids are supposed to be unique. We got 2 allocation recordings with "
|
816
|
-
"the same id. previous=%"PRIsVALUE" new=%"PRIsVALUE, existing_inspect, new_inspect);
|
817
|
-
}
|
734
|
+
|
735
|
+
// This is not supposed to happen, raising...
|
736
|
+
VALUE existing_inspect = object_record_inspect(existing_record);
|
737
|
+
VALUE new_inspect = object_record_inspect(new_object_record);
|
738
|
+
rb_raise(rb_eRuntimeError, "Object ids are supposed to be unique. We got 2 allocation recordings with "
|
739
|
+
"the same id. previous=%"PRIsVALUE" new=%"PRIsVALUE, existing_inspect, new_inspect);
|
818
740
|
}
|
819
741
|
// Always carry on with the update, we want the new record to be there at the end
|
820
742
|
(*value) = (st_data_t) new_object_record;
|
@@ -17,7 +17,7 @@
|
|
17
17
|
typedef struct heap_recorder heap_recorder;
|
18
18
|
|
19
19
|
// Extra data associated with each live object being tracked.
|
20
|
-
typedef struct
|
20
|
+
typedef struct {
|
21
21
|
// The weight of this object from a sampling perspective.
|
22
22
|
//
|
23
23
|
// A notion of weight is preserved for each tracked object to allow for an approximate
|
@@ -13,13 +13,13 @@ static VALUE error_symbol = Qnil; // :error in Ruby
|
|
13
13
|
|
14
14
|
static VALUE library_version_string = Qnil;
|
15
15
|
|
16
|
-
struct
|
16
|
+
typedef struct {
|
17
17
|
ddog_prof_Exporter *exporter;
|
18
18
|
ddog_prof_Exporter_Request_BuildResult *build_result;
|
19
19
|
ddog_CancellationToken *cancel_token;
|
20
20
|
ddog_prof_Exporter_SendResult result;
|
21
21
|
bool send_ran;
|
22
|
-
};
|
22
|
+
} call_exporter_without_gvl_arguments;
|
23
23
|
|
24
24
|
static inline ddog_ByteSlice byte_slice_from_ruby_string(VALUE string);
|
25
25
|
static VALUE _native_validate_exporter(VALUE self, VALUE exporter_configuration);
|
@@ -165,7 +165,7 @@ static VALUE perform_export(
|
|
165
165
|
|
166
166
|
// We'll release the Global VM Lock while we're calling send, so that the Ruby VM can continue to work while this
|
167
167
|
// is pending
|
168
|
-
|
168
|
+
call_exporter_without_gvl_arguments args =
|
169
169
|
{.exporter = exporter, .build_result = &build_result, .cancel_token = cancel_token, .send_ran = false};
|
170
170
|
|
171
171
|
// We use rb_thread_call_without_gvl2 instead of rb_thread_call_without_gvl as the gvl2 variant never raises any
|
@@ -300,7 +300,7 @@ static VALUE _native_do_export(
|
|
300
300
|
}
|
301
301
|
|
302
302
|
static void *call_exporter_without_gvl(void *call_args) {
|
303
|
-
|
303
|
+
call_exporter_without_gvl_arguments *args = (call_exporter_without_gvl_arguments*) call_args;
|
304
304
|
|
305
305
|
args->result = ddog_prof_Exporter_send(args->exporter, &args->build_result->ok, args->cancel_token);
|
306
306
|
args->send_ran = true;
|
@@ -158,7 +158,7 @@ bool is_current_thread_holding_the_gvl(void) {
|
|
158
158
|
//
|
159
159
|
// Thus an incorrect `is_current_thread_holding_the_gvl` result may lead to issues inside `rb_postponed_job_register_one`.
|
160
160
|
//
|
161
|
-
// For this reason we
|
161
|
+
// For this reason we default to use the "no signals workaround" on Ruby 2.5 by default, and we print a
|
162
162
|
// warning when customers force-enable it.
|
163
163
|
bool gvl_acquired = vm->gvl.acquired != 0;
|
164
164
|
rb_thread_t *current_owner = vm->running_thread;
|
@@ -800,3 +800,6 @@ static inline int ddtrace_imemo_type(VALUE imemo) {
|
|
800
800
|
return current_thread;
|
801
801
|
}
|
802
802
|
#endif
|
803
|
+
|
804
|
+
// Is the VM smack in the middle of raising an exception?
|
805
|
+
bool is_raised_flag_set(VALUE thread) { return thread_struct_from_object(thread)->ec->raised_flag > 0; }
|
@@ -18,7 +18,7 @@ typedef struct {
|
|
18
18
|
rb_nativethread_id_t owner;
|
19
19
|
} current_gvl_owner;
|
20
20
|
|
21
|
-
typedef struct
|
21
|
+
typedef struct {
|
22
22
|
union {
|
23
23
|
struct {
|
24
24
|
VALUE iseq;
|
@@ -68,3 +68,5 @@ const char *imemo_kind(VALUE imemo);
|
|
68
68
|
|
69
69
|
#define ENFORCE_THREAD(value) \
|
70
70
|
{ if (RB_UNLIKELY(!rb_typeddata_is_kind_of(value, RTYPEDDATA_TYPE(rb_thread_current())))) raise_unexpected_type(value, ADD_QUOTES(value), "Thread", __FILE__, __LINE__, __func__); }
|
71
|
+
|
72
|
+
bool is_raised_flag_set(VALUE thread);
|
@@ -11,6 +11,7 @@
|
|
11
11
|
#include "ruby_helpers.h"
|
12
12
|
#include "setup_signal_handler.h"
|
13
13
|
#include "time_helpers.h"
|
14
|
+
#include "unsafe_api_calls_check.h"
|
14
15
|
|
15
16
|
// Each class/module here is implemented in their separate file
|
16
17
|
void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module);
|
@@ -56,6 +57,7 @@ void DDTRACE_EXPORT Init_datadog_profiling_native_extension(void) {
|
|
56
57
|
collectors_thread_context_init(profiling_module);
|
57
58
|
http_transport_init(profiling_module);
|
58
59
|
stack_recorder_init(profiling_module);
|
60
|
+
unsafe_api_calls_check_init();
|
59
61
|
|
60
62
|
// Hosts methods used for testing the native code using RSpec
|
61
63
|
VALUE testing_module = rb_define_module_under(native_extension_module, "Testing");
|
@@ -83,16 +85,16 @@ static VALUE native_working_p(DDTRACE_UNUSED VALUE _self) {
|
|
83
85
|
return Qtrue;
|
84
86
|
}
|
85
87
|
|
86
|
-
struct
|
88
|
+
typedef struct {
|
87
89
|
VALUE exception_class;
|
88
90
|
char *test_message;
|
89
91
|
int test_message_arg;
|
90
|
-
};
|
92
|
+
} trigger_grab_gvl_and_raise_arguments;
|
91
93
|
|
92
94
|
static VALUE _native_grab_gvl_and_raise(DDTRACE_UNUSED VALUE _self, VALUE exception_class, VALUE test_message, VALUE test_message_arg, VALUE release_gvl) {
|
93
95
|
ENFORCE_TYPE(test_message, T_STRING);
|
94
96
|
|
95
|
-
|
97
|
+
trigger_grab_gvl_and_raise_arguments args;
|
96
98
|
|
97
99
|
args.exception_class = exception_class;
|
98
100
|
args.test_message = StringValueCStr(test_message);
|
@@ -108,7 +110,7 @@ static VALUE _native_grab_gvl_and_raise(DDTRACE_UNUSED VALUE _self, VALUE except
|
|
108
110
|
}
|
109
111
|
|
110
112
|
static void *trigger_grab_gvl_and_raise(void *trigger_args) {
|
111
|
-
|
113
|
+
trigger_grab_gvl_and_raise_arguments *args = (trigger_grab_gvl_and_raise_arguments *) trigger_args;
|
112
114
|
|
113
115
|
if (args->test_message_arg >= 0) {
|
114
116
|
grab_gvl_and_raise(args->exception_class, "%s%d", args->test_message, args->test_message_arg);
|
@@ -119,16 +121,16 @@ static void *trigger_grab_gvl_and_raise(void *trigger_args) {
|
|
119
121
|
return NULL;
|
120
122
|
}
|
121
123
|
|
122
|
-
struct
|
124
|
+
typedef struct {
|
123
125
|
int syserr_errno;
|
124
126
|
char *test_message;
|
125
127
|
int test_message_arg;
|
126
|
-
};
|
128
|
+
} trigger_grab_gvl_and_raise_syserr_arguments;
|
127
129
|
|
128
130
|
static VALUE _native_grab_gvl_and_raise_syserr(DDTRACE_UNUSED VALUE _self, VALUE syserr_errno, VALUE test_message, VALUE test_message_arg, VALUE release_gvl) {
|
129
131
|
ENFORCE_TYPE(test_message, T_STRING);
|
130
132
|
|
131
|
-
|
133
|
+
trigger_grab_gvl_and_raise_syserr_arguments args;
|
132
134
|
|
133
135
|
args.syserr_errno = NUM2INT(syserr_errno);
|
134
136
|
args.test_message = StringValueCStr(test_message);
|
@@ -144,7 +146,7 @@ static VALUE _native_grab_gvl_and_raise_syserr(DDTRACE_UNUSED VALUE _self, VALUE
|
|
144
146
|
}
|
145
147
|
|
146
148
|
static void *trigger_grab_gvl_and_raise_syserr(void *trigger_args) {
|
147
|
-
|
149
|
+
trigger_grab_gvl_and_raise_syserr_arguments *args = (trigger_grab_gvl_and_raise_syserr_arguments *) trigger_args;
|
148
150
|
|
149
151
|
if (args->test_message_arg >= 0) {
|
150
152
|
grab_gvl_and_raise_syserr(args->syserr_errno, "%s%d", args->test_message, args->test_message_arg);
|
@@ -23,18 +23,18 @@ void ruby_helpers_init(void) {
|
|
23
23
|
|
24
24
|
#define MAX_RAISE_MESSAGE_SIZE 256
|
25
25
|
|
26
|
-
struct
|
26
|
+
typedef struct {
|
27
27
|
VALUE exception_class;
|
28
28
|
char exception_message[MAX_RAISE_MESSAGE_SIZE];
|
29
|
-
};
|
29
|
+
} raise_args;
|
30
30
|
|
31
31
|
static void *trigger_raise(void *raise_arguments) {
|
32
|
-
|
32
|
+
raise_args *args = (raise_args *) raise_arguments;
|
33
33
|
rb_raise(args->exception_class, "%s", args->exception_message);
|
34
34
|
}
|
35
35
|
|
36
36
|
void grab_gvl_and_raise(VALUE exception_class, const char *format_string, ...) {
|
37
|
-
|
37
|
+
raise_args args;
|
38
38
|
|
39
39
|
args.exception_class = exception_class;
|
40
40
|
|
@@ -55,18 +55,18 @@ void grab_gvl_and_raise(VALUE exception_class, const char *format_string, ...) {
|
|
55
55
|
rb_bug("[ddtrace] Unexpected: Reached the end of grab_gvl_and_raise while raising '%s'\n", args.exception_message);
|
56
56
|
}
|
57
57
|
|
58
|
-
struct
|
58
|
+
typedef struct {
|
59
59
|
int syserr_errno;
|
60
60
|
char exception_message[MAX_RAISE_MESSAGE_SIZE];
|
61
|
-
};
|
61
|
+
} syserr_raise_args;
|
62
62
|
|
63
63
|
static void *trigger_syserr_raise(void *syserr_raise_arguments) {
|
64
|
-
|
64
|
+
syserr_raise_args *args = (syserr_raise_args *) syserr_raise_arguments;
|
65
65
|
rb_syserr_fail(args->syserr_errno, args->exception_message);
|
66
66
|
}
|
67
67
|
|
68
68
|
void grab_gvl_and_raise_syserr(int syserr_errno, const char *format_string, ...) {
|
69
|
-
|
69
|
+
syserr_raise_args args;
|
70
70
|
|
71
71
|
args.syserr_errno = syserr_errno;
|
72
72
|
|