datadog 2.7.1 → 2.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|